Server Code :
#POST
#Path("reportDownload")
#Consumes(MediaType.APPLICATION_JSON)
public Response generateReport(QueryData queryData) {
File file = new File("report.xlsx") // large file
StreamingOutput stream = new FileStreamingOutput(file) ;
return Response.ok(stream, MediaType.APPLICATION_OCTET_STREAM)
.header("filename" , file.getName())
.build();
}
Client Code :
Using the following code I'm able to download files upto some limit. Getting out of memory heap error for large files.
final String uri = buildUri("/reportGenerate/reportDownload");
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setReadTimeout(read_timeout);
factory.setConnectTimeout(connection_timeout);
RestTemplate restTemplate = new RestTemplate(factory);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
List<MediaType> mediaTypeList = new ArrayList<>();
mediaTypeList.add(MediaType.APPLICATION_OCTET_STREAM);
headers.setAccept(mediaTypeList);
HttpEntity entity = new HttpEntity(queryData, headers);
ResponseEntity<byte[]> data = restTemplate.exchange(uri, HttpMethod.POST, entity, byte[].class);
HttpHeaders responseHeader = data.getHeaders();
String fileName = (String) responseHeader.get("filename").get(0);
String downloadFolder = ApplicationConfig.REPORT_DOWNLOAD_FOLDER.getValue();
if (data.getStatusCode() == HttpStatus.OK) {
FileOutputStream fos = null;
File toFile = null;
try {
toFile = new File(downloadFolder + File.separator + fileName);
fos = new FileOutputStream(toFile);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
IOUtils.write(data.getBody(), bos);
bos.writeTo(fos);
} catch (Exception e) {
convertReportException(e);
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException ex) {
convertReportException(ex);
}
}
return toFile;
}
}
How to use stream for download larger files.
Here is how I do it with a ResponseExtractor. Based on hints from this Spring Jira issue.
RestTemplate restTemplate // = ...;
// Optional Accept header
RequestCallback requestCallback = request -> request.getHeaders()
.setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL));
// Streams the response instead of loading it all in memory
ResponseExtractor<Void> responseExtractor = response -> {
// Here I write the response to a file but do what you like
Path path = Paths.get("some/path");
Files.copy(response.getBody(), path);
return null;
};
restTemplate.execute(URI.create("www.something.com"), HttpMethod.GET, requestCallback, responseExtractor);
update
Here is what RestTemplate does behind the scenes on postForObject and friends (inline comments from me):
#Override
public <T> T postForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
throws RestClientException {
// From RequestCallback's javadoc:
// Callback interface for code that operates on a ClientHttpRequest.
// Allows to manipulate the request headers, and write to the request body.
//
// Used internally by the RestTemplate, but also useful for application code.
RequestCallback requestCallback = httpEntityCallback(request, responseType);
// HttpMessageConverterExtractor checks the response type header and requested
// responseType class to select the proper message converter to handle the response.
// It also implements ResponseExtractor.
HttpMessageConverterExtractor<T> responseExtractor =
new HttpMessageConverterExtractor<T>(responseType, getMessageConverters(), logger);
return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
}
/**
* Returns a request callback implementation that writes the given object to the
* request stream.
*/
protected <T> RequestCallback httpEntityCallback(Object requestBody, Type responseType) {
return new HttpEntityRequestCallback(requestBody, responseType);
}
Note: This is essentially a duplicate of my answer at https://stackoverflow.com/a/38664475/1030527 but I can't mark the questions as duplicate since neither this one or that one have upvoted answers.
At the client that you mentioned
don't store the file in memory to download a large via the RestTemplate, it can cause the Java heap exception.
it should be stored on disk.
Here is some code sample to download a large file via the RestTemplate
#GetMapping("largeFile")
public ResponseEntity<InputStreamResource> downloadLargeFile(
#RequestParam("fileName") String fileName
) throws IOException {
RestTemplate restTemplate = new RestTemplate();
// Optional Accept header
RequestCallback requestCallback = request -> request.getHeaders()
.setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL));
// Streams the response instead of loading it all in memory
ResponseExtractor<InputStreamResource> responseExtractor = response -> {
// Here I write the response to a file but do what you like
Path path = Paths.get("tmp/" + fileName);
Files.copy(response.getBody(), path, StandardCopyOption.REPLACE_EXISTING);
return new InputStreamResource(new FileInputStream(String.format("tmp/%s", fileName)));
};
InputStreamResource response = restTemplate.execute(
String.format("http://%s:%s/file/largeFileRestTemplate?fileName=%s", host, "9091", fileName),
HttpMethod.GET,
requestCallback,
responseExtractor
);
return ResponseEntity
.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, String.format("attachment; filename=%s", fileName))
.body(response);
}
Related
I am new to resttemplate and trying to understand how to invoke below API using restTemplate
public ResponseEntity<String> upload(#ResquestPart("file") MultipartFIle file,
#RequestParam("path") String path){
//businness logic
}
I am trying to call above as below however it fails on "java.io.filenotfoundexception multipartfile resource [ABC.txt]cannot be resolved to absolute file path"
public void uploadFile() {
Path path = Paths.get("C:/ABC.txt");
byte[] content = null;
try{
content = Files.readAllBytes(path); // All file is read in content variable
} catch(final IOException e){
}
MultipartFile file = new MockMultipartFile("ABC.txt",content);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
headers.setContentType("Accept", Mediatype.APPLICATION_JSON_VALUE);
headers.setContentType("Content-type", Mediatype.APPLICATION_JSON_VALUE);
MultiValueMap<String, Object> obj = new LinkedMultiValueMap<String, Object>();
obj.add("file", file);
obj.add9("path", "/opt/apps");
HttpEntity<?> requestEntity = new HttpEntity<>(obj, headers);
String result = getRestTemplate().postForEntity("url", requestEntity, String.class);
}
I have a controller in gateway microservice that accepts the MultipartFile and resends to the service behind it
#PostMapping
public ResponseEntity upload(#ApiParam(name = "file", value = "File", required = true) MultipartFile file)
throws BaseException {
if (Objects.isNull(file)){
throw new CheckFieldException("file", MultipartFile.class);
}
if (megabyte * maxFileSize - file.getSize() < 0){
return ResponseEntity.accepted().body(new DocumentResponseDTO(false, "File size exceeds " + maxFileSize + "MB"));
}
DiscoveryConfig.CashTracking config = discoveryConfig.getCashTracking();
UriComponents uriStatementUpload = UriComponentsBuilder.newInstance().scheme(config.getScheme())
.host(config.getHost()).port(config.getPort()).path(config.getExcelNominalOperationsPath()).build(true);
try {
HttpEntity<byte[]> fileEntity = new HttpEntity(file.getBytes());
ResponseEntity<DocumentResponseDTO> entity = restTemplate.postForEntity(uriStatementUpload.toUri(), fileEntity, DocumentResponseDTO.class);
return entity;
} catch (HttpClientErrorException e) {
return ResponseEntity.status(e.getStatusCode()).body(e.getResponseBodyAsString());
} catch (IOException e) {
return ResponseEntity.status(500).body("IOException while getting bytes stream from file");
}
}
and in CashTracking service there is also file upload like that:
#PostMapping(value = "/upload")
public ResponseEntity uploadExcelNominalOperationsFile(#ApiParam(name = "file", value = "File", required = true) MultipartFile file) throws IOException {
try (InputStream is = file.getInputStream()) {
log.info("Processing incoming Excel file with nominal operations");
Workbook workbook = new XSSFWorkbook(is);
log.info("Processing workbook");
Sheet sheet = workbook.getSheetAt(0);
log.info("Processing the first sheet");
List<NominalOperationVO> nominalOperationVOs = new ArrayList<>();
List<String> fileHeaders = new ArrayList<>();
And when the file is actually uploaded to the gateway service, the service behind it starts processing the file upload, but the MultipartFile file is null. I have explicitly put it in the Entity I have sent to the service behind the gateway, the question, what I'm doing wrong if it is null? If I do upload to that microservice directly, it process the request correctly.
The main stuff I was missing was putting the Http headers per specific multipart form's parts. They should be identical to what has been sent to the gateway service.
public ResponseEntity upload(#ApiParam(name = "file", value = "Файл", required = true) MultipartFile file)
throws BaseException {
if (Objects.isNull(file)){
throw new CheckFieldException("file", MultipartFile.class);
}
if (megabyte * maxFileSize - file.getSize() < 0){
return ResponseEntity.accepted().body(new DocumentResponseDTO(false, "File size exceeds " + maxFileSize + "MB"));
}
DiscoveryConfig.CashTracking config = discoveryConfig.getCashTracking();
UriComponents uriStatementUpload = UriComponentsBuilder.newInstance().scheme(config.getScheme())
.host(config.getHost()).port(config.getPort()).path(config.getExcelNominalOperationsPath()).build(true);
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultipartBodyBuilder multipartBodyBuilder = new MultipartBodyBuilder();
//here is the really needed stuff with 2 headers
Resource resource = new ByteArrayResource(file.getBytes());
multipartBodyBuilder.part("file", resource)
.header("Content-Type",file.getContentType())
.header("Content-Disposition","form-data; name=\"file\"; filename=\""+file.getOriginalFilename()+"\"");
// multipart/form-data request body
MultiValueMap<String, HttpEntity<?>> body = multipartBodyBuilder.build();
HttpEntity<MultiValueMap<String, HttpEntity<?>>> requestEntity
= new HttpEntity<>(body, headers);
ResponseEntity<DocumentResponseDTO> entity = restTemplate.postForEntity(uriStatementUpload.toUri(), requestEntity, DocumentResponseDTO.class);
return entity;
} catch (HttpClientErrorException e) {
return ResponseEntity.status(e.getStatusCode()).body(e.getResponseBodyAsString());
} catch (IOException e) {
return ResponseEntity.status(500).body("IOException while getting bytes stream from file");
}
}
I am using RestTemplate to access a service.
RestTemplate rt = new RestTemplate ();
HttpEntity <String> he = new HttpEntity <String> (output, hh);
ResponseEntity <String> re = rt.exchange ("http://localhost:8080/my", HttpMethod.GET, he, String.class);
ResponseEntity has getBody and getHeaders for accessing the response.
getHeaders is already a parsed list of the header-lines.
Is there a way I can get the raw response as one big junk of bytes?
For that you will use following signature of execute method :
execute(URI url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor<T> responseExtractor)
This method will execute the HTTP method to the given URL, preparing the request with the RequestCallback, and reading the response with a ResponseExtractor.
Next step is to write a custom implementation for ResponseExtractor interface and override extractData() which is responsible for extracting data from response.
Here is example.
First, write some dummy method in controller class, something like this :
#PostMapping(value = "/hello")
public String test() {
return "Hello world";
}
Then, write method which will call method above using restTemplate and return response as byte array:
#GetMapping("/test")
public void test() throws IOException {
final URI url = URI.create("http://localhost:8080/hello");
final Map<String, String> headers = new HashMap<>();
headers.put("Accept", "application/json");
// Here you can set headers, request body,query parans,ect..
RequestCallback requestCallback = r -> {
//example: r.getBody().write(("username=" + username).getBytes());
r.getHeaders().setAll(headers);
};
byte[] res = restTemplate.execute(url, HttpMethod.POST, requestCallback, new ResponseExtractor<byte[]>() {
#Override
public byte[] extractData(ClientHttpResponse response) throws IOException {
byte[] data = new byte[1024];
// return data from response as byte array
response.getBody().read(data);
return data;
}
});
//write result in console
ByteArrayInputStream byteArrayInputStr
= new ByteArrayInputStream(res);
int b = 0;
while ((b = byteArrayInputStr.read()) != -1) {
char ch = (char) b;
System.out.println("Char : " + ch);
}
}
If you execute test() method, you should see output like this:
Right now I have 2 Spring App.
App A will have a controller that will receive a video file ad Multipart file and sending the file to App B via rest template.
Some Code from App A that handle sending request to App B.
#RestController
public class AppAController {
#Autowired
private final AppBService service;
#PostMapping("/sendToB")
public ResponseEntity<String> contoller(#RequestParam("file") MultipartFile file) {
String result = service.sendToB(file);
return new ResponseEntity<>(result, HttpStatus.OK);
}
}
#Service
public class AppBService {
public String sendToB(MultipartFile file) throws ResponseStatusException {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file", file);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
String serverUrl = "http://127.0.0.1:8090/makeFrames";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.exchange(
serverUrl,
HttpMethod.POST,
requestEntity,
String.class
);
if (response.getStatusCode() != HttpStatus.OK) {
throw new ResponseStatusException(response.getStatusCode(), response.getBody());
}
return response.getBody();
}
}
And for App B, it will receive a video and extracting key frames from a video using JavaCV.
#RestController
public class ProcessorController {
#PostMapping("/makeFrames")
public ResponseEntity<String> framesExtractorController(#RequestParam("file") MultipartFile file) {
try {
File result = FramesExtractor.grabFrames(file);
return new ResponseEntity<>(result.getAbsolutePath(), HttpStatus.OK);
} catch (IOException e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.NOT_FOUND);
}
}
}
public class FramesExtractor {
private static final Logger LOG = LoggerFactory.getLogger(FramesExtractor.class);
private FramesExtractor() {
}
public static File grabFrames(MultipartFile video) throws IOException {
LOG.info("Extracting Frames from the video " + video.getName());
String directoryName = video.getOriginalFilename() + "-frames-result";
directoryAssurance(directoryName);
try (FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber(video.getInputStream());
Java2DFrameConverter converter = new Java2DFrameConverter()) {
frameGrabber.setImageWidth(480);
frameGrabber.setImageHeight(360);
frameGrabber.start();
Frame frame;
int i = 0;
while ((frame = frameGrabber.grabKeyFrame()) != null) {
BufferedImage bi = converter.getBufferedImage(frame);
ImageIO.write(bi, "png", new File(directoryName + "/" + String.format("%03d", i) + ".png"));
i++;
}
frameGrabber.stop();
LOG.info("Finish Extracting Frames");
return new File(directoryName);
} catch (Exception e) {
LOG.error(e.getMessage());
throw e;
}
}
}
Both app A and B have these properties set to their application.properties files.
server.port={There respective port}
spring.servlet.multipart.enabled=true
spring.servlet.multipart.max-file-size=100MB
spring.servlet.multipart.max-request-size=100MB
And when i testing the application by using PostMan to send post request with video file in form-data body to App A /sendToB api i receive this error message.
"Type definition error: [simple type, class java.io.FileDescriptor]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.io.FileDescriptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile[\"inputStream\"]->java.io.FileInputStream[\"fd\"])"
So I want to ask what cause this problems and how I can fix it or sending video file to other Spring App running on other port properly.
I edited my previous answer because you can actually get parameters from a response body in a POST with #RequestParam annotation.
I would use JSON as content type. This is my solution:
public String sendToB(MultipartFile file) throws ResponseStatusException {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
byte[] bytesFile = file.getBytes();
String base64String = Base64.getEncoder().encodeToString(bytesFile);
Map<String, Object> body = new HashMap<>();
body.put("file", base64String);
body.put("directoryName", file.getOriginalFilename());
body.put("videoName", file.getName())
HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(body, headers);
String serverUrl = "http://127.0.0.1:8090/makeFrames";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.exchange(
serverUrl,
HttpMethod.POST,
requestEntity,
String.class
);
if (response.getStatusCode() != HttpStatus.OK) {
throw new ResponseStatusException(response.getStatusCode(), response.getBody());
}
return response.getBody();
}
For App B, the code would be:
#PostMapping("/makeFrames")
public ResponseEntity<String> framesExtractorController(#RequestBody Map<String, Object> requestBody) {
try {
String base64String = requestBody.get("file").toString();
byte[] bytesFile = Base64.getDecoder().decode(base64String);
InputStream inputStream = new ByteArrayInputStream(bytesFile);
String directoryName = requestBody.get("directoryName").toString();
String videoName = requestBody.get("videoName").toString();
File result = FramesExtractor.grabFrames(inputStream, directoryName, videoName);
return new ResponseEntity<>(result.getAbsolutePath(), HttpStatus.OK);
} catch (IOException e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.NOT_FOUND);
}
}
}
public static File grabFrames(InputStream inputStream, String directoryName, String videoName) throws IOException {
//Your code
}
I'm trying to consume a web service that accepts a CommonsMultipartFile in the request. So, I created an HTTP client using Spring's RestTemplate. Below is the method that takes in URI and a MultipartFile as parameters. I'm trying to pass this file to the web service in the form of ByteArrayResource.
public String upload(String uri, MultipartFile file) throws IOException {
logger.info("URI: " + uri);
ByteArrayResource fileAsResource = new ByteArrayResource(file.getBytes()) {
#Override
public String getFilename() {
return file.getOriginalFilename();
}
};
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
parts.add("file", fileAsResource);
parts.add("fileName", file.getOriginalFilename());
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<MultiValueMap<String, Object>>(parts, httpHeaders);
ResponseEntity<String> responseEntity = rest.exchange(uri, HttpMethod.POST, requestEntity, String.class);
this.setStatus(responseEntity.getStatusCode());
return responseEntity.getBody();
}
This is how I'm creating a CommonsMultipartFile:
private MultipartFile getCommonsMultipartFile() throws FileNotFoundException, IOException {
File file = new File("C:\\Dummy_Test.txt");
DiskFileItemFactory factory = new DiskFileItemFactory();
FileItem fileItem = factory.createItem( "file", "multipart/form-data", false, "Dummy_Test.txt" );
IOUtils.copy(new FileInputStream(file), fileItem.getOutputStream());
MultipartFile commonsMultipartFile = new CommonsMultipartFile(fileItem);
return commonsMultipartFile;
}
But whenever I run this client to hit the web service I keep getting this error.
org.springframework.web.client.ResourceAccessException: I/O error: resource loaded from byte array cannot be resolved to absolute file path; nested exception is java.io.FileNotFoundException: resource loaded from byte array cannot be resolved to absolute file path
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:453)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:401)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:377)
at com.attikala.service.UploaderService.upload(UploaderService.java:118)
at com.attikala.service.UploaderService.main(UploaderService.java:55)
Caused by: java.io.FileNotFoundException: resource loaded from byte array cannot be resolved to absolute file path
at org.springframework.core.io.AbstractResource.getFile(AbstractResource.java:107)
at org.springframework.core.io.AbstractResource.contentLength(AbstractResource.java:116)
at org.springframework.http.converter.ResourceHttpMessageConverter.getContentLength(ResourceHttpMessageConverter.java:99)
at org.springframework.http.converter.ResourceHttpMessageConverter.write(ResourceHttpMessageConverter.java:81)
at org.springframework.http.converter.ResourceHttpMessageConverter.write(ResourceHttpMessageConverter.java:1)
at org.springframework.http.converter.FormHttpMessageConverter.writePart(FormHttpMessageConverter.java:288)
at org.springframework.http.converter.FormHttpMessageConverter.writeParts(FormHttpMessageConverter.java:252)
at org.springframework.http.converter.FormHttpMessageConverter.writeMultipart(FormHttpMessageConverter.java:242)
at org.springframework.http.converter.FormHttpMessageConverter.write(FormHttpMessageConverter.java:194)
at org.springframework.http.converter.FormHttpMessageConverter.write(FormHttpMessageConverter.java:1)
at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:588)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:436)
... 4 more
Can someone help me in figuring out what's happening here?
Note: If I use the below code to upload the file, it works perfectly fine.
public String upload(String uri) {
LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
FileSystemResource value = new FileSystemResource(new File("C:\\Dummy_Test.txt"));
map.add("file", value);
map.add("fileName", "Dummy_Test.txt");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> responseEntity = restTemplate.exchange(uri, HttpMethod.POST, requestEntity, String.class);
return responseEntity.getBody();
}
So, I'm thinking, do I need to provide absolute path always for the file I'm uploading? I know I'm missing something here. Don't know what.
Thanks.
Finally, I found what's happening.
Here I go -
when this statement
ResponseEntity<String> responseEntity = rest.exchange(uri, HttpMethod.POST, requestEntity, String.class);
gets executed, behind the scenes it's trying to extract the file of type java.io.File from the MultipartFile passed, and then get the file length. But MultipartFile is not of that type and as a result it was throwing an exception.
To fix that I had to also override contentLength() method when creating an instance of ByteArrayResource. Ta-da!
ByteArrayResource fileAsResource = new ByteArrayResource(file.getBytes()) {
#Override
public String getFilename() {
return file.getOriginalFilename();
}
#Override
public long contentLength() throws IOException {
return file.getSize();
}
};
Hope this helps if anyone runs into the same problem.
The accepted answer did not work. In my case I had to override the getFile(), see my solution below.
registry.addResourceHandler("/my-app/user-tracking-script.js")
.setCachePeriod(0)
.resourceChain(false)
.addResolver(new ResourceResolver() {
#Override
public Resource resolveResource(final HttpServletRequest request, final String requestPath, final List<? extends Resource> locations, final ResourceResolverChain chain) {
try {
final HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM));
final HttpEntity<String> entity = new HttpEntity<>(headers);
// RELEVANT PART BELOW
final ResponseEntity<byte[]> response = restTemplate.exchange(userTrackingScript, HttpMethod.GET, entity, byte[].class);
final ByteArrayResource fileAsResource = new ByteArrayResource(response.getBody()) {
#Override
public File getFile() throws IOException {
final File tempFile = File.createTempFile("user-tracking", ".js");
try (final FileOutputStream out = new FileOutputStream(tempFile)) {
IOUtils.copy(new ByteArrayInputStream(response.getBody()), out);
}
return tempFile;
}
};
return fileAsResource;
} catch (final Exception e) {
log.error("Could not download user-tracking-script.js for URL: {}", userTrackingScript, e);
}
return null;
}
#Override
public String resolveUrlPath(final String resourcePath, final List<? extends Resource> locations, final ResourceResolverChain chain) {
log.error("Unexpected call to resolveUrlPath by {}", resourcePath);
return null;
}
})
;