Skip to content

Commit

Permalink
fix: repository entity multipart controller should use request mappin…
Browse files Browse the repository at this point in the history
…g context to map requested content property (#1968)
  • Loading branch information
paulcwarren authored May 31, 2024
1 parent 20881dc commit 2164d6f
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import internal.org.springframework.content.rest.controllers.MethodNotAllowedException;
import internal.org.springframework.content.rest.controllers.resolvers.AssociativeStoreResourceResolver;
import internal.org.springframework.content.rest.mappingcontext.ContentPropertyToExportedContext;
import internal.org.springframework.content.rest.mappingcontext.ContentPropertyToRequestMappingContext;
import internal.org.springframework.content.rest.mappings.StoreByteRangeHttpRequestHandler;
import internal.org.springframework.content.rest.utils.ControllerUtils;
import internal.org.springframework.content.rest.utils.StoreUtils;
Expand All @@ -22,11 +23,7 @@
import org.springframework.data.repository.support.RepositoryInvokerFactory;
import org.springframework.data.rest.core.mapping.ResourceType;
import org.springframework.data.rest.core.support.SelfLinkProvider;
import org.springframework.data.rest.webmvc.HttpHeadersPreparer;
import org.springframework.data.rest.webmvc.PersistentEntityResource;
import org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler;
import org.springframework.data.rest.webmvc.RepositoryRestController;
import org.springframework.data.rest.webmvc.RootResourceInformation;
import org.springframework.data.rest.webmvc.*;
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurer;
import org.springframework.hateoas.RepresentationModel;
import org.springframework.hateoas.UriTemplate;
Expand All @@ -44,9 +41,11 @@

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.security.Principal;
import java.util.*;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;

@RepositoryRestController
public class RepositoryEntityMultipartController {
Expand All @@ -55,6 +54,7 @@ public class RepositoryEntityMultipartController {

private RestConfiguration restConfig;
private RepositoryInvokerFactory repoInvokerFactory;
private ContentPropertyToRequestMappingContext requestMappingContext;
private MappingContext mappingContext;
private ContentPropertyToExportedContext exportedMappingContext;
private StoreByteRangeHttpRequestHandler byteRangeRestRequestHandler;
Expand All @@ -63,9 +63,10 @@ public class RepositoryEntityMultipartController {
private HttpHeadersPreparer headersPreparer;

@Autowired
public RepositoryEntityMultipartController(RestConfiguration restConfig, RepositoryInvokerFactory repoInvokerFactory, SelfLinkProvider selfLinkProvider, Stores stores, MappingContext mappingContext, ContentPropertyToExportedContext exportedMappingContext, StoreByteRangeHttpRequestHandler byteRangeRestRequestHandler, @Qualifier("entityMultipartHttpMessageConverterConfigurer") RepositoryRestConfigurer configurer, HttpHeadersPreparer headersPreparer) {
public RepositoryEntityMultipartController(RestConfiguration restConfig, RepositoryInvokerFactory repoInvokerFactory, ContentPropertyToRequestMappingContext requestMappingContext, SelfLinkProvider selfLinkProvider, Stores stores, MappingContext mappingContext, ContentPropertyToExportedContext exportedMappingContext, StoreByteRangeHttpRequestHandler byteRangeRestRequestHandler, @Qualifier("entityMultipartHttpMessageConverterConfigurer") RepositoryRestConfigurer configurer, HttpHeadersPreparer headersPreparer) {
this.restConfig = restConfig;
this.repoInvokerFactory = repoInvokerFactory;
this.requestMappingContext = requestMappingContext;
this.selfLinkProvider = selfLinkProvider;
this.stores = stores;
this.mappingContext = mappingContext;
Expand Down Expand Up @@ -105,7 +106,11 @@ public ResponseEntity<RepresentationModel<?>> createEntityAndContent(RootResourc
for (String path : files.keySet()) {
MultipartFile file = files.get(path).get(0);

Resource storeResource = new AssociativeStoreResourceResolver(mappingContext).resolve(new InternalWebRequest(req, resp), info, savedEntity, PropertyPath.from(file.getName()));
String resolvedPath = file.getName();
if (this.requestMappingContext.hasInverseMapping(domainType, file.getName())) {
resolvedPath = this.requestMappingContext.getInverseMappings(domainType).get(file.getName());
}
Resource storeResource = new AssociativeStoreResourceResolver(mappingContext).resolve(new InternalWebRequest(req, resp), info, savedEntity, PropertyPath.from(resolvedPath));

headers.setContentLength(file.getSize());
service.setContent(req, resp, headers, new InputStreamResourceWithFilename(file.getInputStream(), file.getOriginalFilename()), MediaType.parseMediaType(file.getContentType()), storeResource);
Expand All @@ -122,7 +127,6 @@ public ResponseEntity<RepresentationModel<?>> createEntityAndContent(RootResourc
headers.setContentType(new MediaType("application", "hal+json"));

HttpHeaders respHeaders = headersPreparer.prepareHeaders(resource);
// addLocationHeader(respHeaders, assembler, savedEntity);
String selfLink = selfLinkProvider.createSelfLinkFor(savedEntity).withSelfRel().expand(new Object[0]).getHref();
respHeaders.setLocation(UriTemplate.of(selfLink).expand());
return ControllerUtils.toResponseEntity(HttpStatus.CREATED, respHeaders, resource);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ public class ContentEntityRestEndpointsIT {
@Autowired
TestEntity9Store store9;

// mapped content property
@Autowired
TestEntity11Repository repo11;
@Autowired
TestEntity11Store store11;

@Autowired
TestStore store;

Expand All @@ -92,6 +98,7 @@ public class ContentEntityRestEndpointsIT {
private TestEntity4 testEntity4;
private TestEntity6 testEntity6;
private TestEntity9 testEntity9;
private TestEntity11 testEntity11;

private Version version;
private LastModifiedDate lastModifiedDate;
Expand Down Expand Up @@ -316,12 +323,15 @@ public class ContentEntityRestEndpointsIT {
Optional<TestEntity9> fetchedEntity = repo9.findById(Long.valueOf(StringUtils.substringAfterLast(location, "/")));
assertThat(fetchedEntity.get().getHidden(), is(nullValue()));

// assert that it now exists
response = mvc.perform(get(location)
// assert entity now exists
mvc.perform(head(location))
.andExpect(status().is2xxSuccessful());

// assert content now exists
response = mvc.perform(get(location + "/content")
.accept("text/plain"))
.andExpect(status().isOk())
.andReturn().getResponse();

assertThat(response.getContentAsString(), is(newContent));
});
});
Expand Down Expand Up @@ -355,6 +365,37 @@ public class ContentEntityRestEndpointsIT {
assertThat(fetchedEntity.get().getOriginalFileName(), is(nullValue()));
});
});

Context("given a a multipart/form POST to an entity with a mapped content property", () -> {
It("should create a new entity and its content and respond with a 201 Created", () -> {
// assert content does not exist
String newContent = "This is some new content";

MockMultipartFile file = new MockMultipartFile("package/content", "filename.txt", "text/plain", newContent.getBytes());

// POST the new content
MockHttpServletResponse response = mvc.perform(multipart("/testEntity11s")
.file(file))
.andExpect(status().isCreated())
.andReturn().getResponse();

String location = response.getHeader("Location");

Optional<TestEntity11> fetchedEntity = repo11.findById(Long.valueOf(StringUtils.substringAfterLast(location, "/")));
assertThat(fetchedEntity.get().get_package().getContentId(), is(not(nullValue())));

// assert entity now exists
mvc.perform(head(location))
.andExpect(status().is2xxSuccessful());

// assert content now exists
response = mvc.perform(get(location + "/package/content")
.accept("text/plain"))
.andExpect(status().isOk())
.andReturn().getResponse();
assertThat(response.getContentAsString(), is(newContent));
});
});
});
}

Expand Down

0 comments on commit 2164d6f

Please sign in to comment.