diff --git a/examples/hawkbit-mgmt-api-client/pom.xml b/examples/hawkbit-mgmt-api-client/pom.xml
index 75e520ea6..70b394ac4 100644
--- a/examples/hawkbit-mgmt-api-client/pom.xml
+++ b/examples/hawkbit-mgmt-api-client/pom.xml
@@ -71,6 +71,11 @@
feign-jackson
8.14.2
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.5.5
+
hibernate-validator
org.hibernate
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/MgmtDefaultFeignClient.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/MgmtDefaultFeignClient.java
index 8bfc2ec52..6425bad4d 100644
--- a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/MgmtDefaultFeignClient.java
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/MgmtDefaultFeignClient.java
@@ -19,6 +19,10 @@ import org.eclipse.hawkbit.mgmt.client.resource.MgmtSoftwareModuleTypeClientReso
import org.eclipse.hawkbit.mgmt.client.resource.MgmtTargetClientResource;
import org.eclipse.hawkbit.mgmt.client.resource.MgmtTargetTagClientResource;
import org.springframework.cloud.netflix.feign.support.ResponseEntityDecoder;
+import org.springframework.hateoas.hal.Jackson2HalModule;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
import feign.Feign;
import feign.Feign.Builder;
@@ -47,10 +51,14 @@ public class MgmtDefaultFeignClient {
private final String baseUrl;
public MgmtDefaultFeignClient(final String baseUrl) {
+ final ObjectMapper mapper = new ObjectMapper()
+ .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
+ .registerModule(new Jackson2HalModule());
+
feignBuilder = Feign.builder().contract(new IgnoreMultipleConsumersProducersSpringMvcContract())
.requestInterceptor(new ApplicationJsonRequestHeaderInterceptor()).logLevel(Level.FULL)
.logger(new Logger.ErrorLogger()).encoder(new JacksonEncoder())
- .decoder(new ResponseEntityDecoder(new JacksonDecoder()));
+ .decoder(new ResponseEntityDecoder(new JacksonDecoder(mapper)));
this.baseUrl = baseUrl;
}
@@ -93,7 +101,7 @@ public class MgmtDefaultFeignClient {
public MgmtSoftwareModuleClientResource getMgmtSoftwareModuleClientResource() {
if (mgmtSoftwareModuleClientResource == null) {
mgmtSoftwareModuleClientResource = feignBuilder.target(MgmtSoftwareModuleClientResource.class,
- MgmtSoftwareModuleClientResource.PATH);
+ this.baseUrl + MgmtSoftwareModuleClientResource.PATH);
}
return mgmtSoftwareModuleClientResource;
}
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/web/ResourceControllerAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/web/ResourceControllerAutoConfiguration.java
index afb90bd13..ae92d3200 100644
--- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/web/ResourceControllerAutoConfiguration.java
+++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/web/ResourceControllerAutoConfiguration.java
@@ -8,12 +8,20 @@
*/
package org.eclipse.hawkbit.autoconfigure.web;
+import javax.servlet.http.HttpServletResponse;
+
import org.eclipse.hawkbit.ddi.EnableDdiApi;
import org.eclipse.hawkbit.mgmt.annotation.EnableMgmtApi;
+import org.eclipse.hawkbit.rest.util.FilterHttpResponse;
+import org.eclipse.hawkbit.rest.util.HttpResponseFactoryBean;
+import org.eclipse.hawkbit.rest.util.RequestResponseContextHolder;
import org.eclipse.hawkbit.system.annotation.EnableSystemApi;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.Scope;
+import org.springframework.web.context.WebApplicationContext;
/**
* Auto-Configuration for enabling the REST-Resources.
@@ -24,4 +32,29 @@ import org.springframework.context.annotation.Import;
@Import({ EnableDdiApi.class, EnableMgmtApi.class, EnableSystemApi.class })
public class ResourceControllerAutoConfiguration {
+ /**
+ * Create filter for {@link HttpServletResponse}.
+ */
+ @Bean
+ public FilterHttpResponse filterHttpResponse() {
+ return new FilterHttpResponse();
+ }
+
+ /**
+ * Create factory bean for {@link HttpServletResponse}.
+ */
+ @Bean
+ public HttpResponseFactoryBean httpResponseFactoryBean() {
+ return new HttpResponseFactoryBean();
+ }
+
+ /**
+ * Create factory bean for {@link HttpServletResponse}.
+ */
+ @Bean
+ @Scope(value = WebApplicationContext.SCOPE_REQUEST)
+ public RequestResponseContextHolder requestResponseContextHolder() {
+ return new RequestResponseContextHolder();
+ }
+
}
diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDownloadArtifactRestApi.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDownloadArtifactRestApi.java
index e07d77f2f..4b50dc8f5 100644
--- a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDownloadArtifactRestApi.java
+++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDownloadArtifactRestApi.java
@@ -8,9 +8,6 @@
*/
package org.eclipse.hawkbit.mgmt.rest.api;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -40,7 +37,6 @@ public interface MgmtDownloadArtifactRestApi {
@RequestMapping(method = RequestMethod.GET, value = "/{softwareModuleId}/artifacts/{artifactId}/download")
@ResponseBody
ResponseEntity downloadArtifact(@PathVariable("softwareModuleId") final Long softwareModuleId,
- @PathVariable("artifactId") final Long artifactId, final HttpServletResponse servletResponse,
- final HttpServletRequest request);
+ @PathVariable("artifactId") final Long artifactId);
}
diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java
index ddd7180cf..de01a917a 100644
--- a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java
+++ b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadArtifactResource.java
@@ -9,7 +9,6 @@
package org.eclipse.hawkbit.mgmt.rest.resource;
import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtDownloadArtifactRestApi;
@@ -18,18 +17,22 @@ import org.eclipse.hawkbit.repository.SoftwareManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
+import org.eclipse.hawkbit.rest.util.RequestResponseContextHolder;
import org.eclipse.hawkbit.rest.util.RestResourceConversionHelper;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Scope;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.context.WebApplicationContext;
/**
*
*/
@RestController
+@Scope(value = WebApplicationContext.SCOPE_REQUEST)
public class MgmtDownloadArtifactResource implements MgmtDownloadArtifactRestApi {
@Autowired
@@ -38,6 +41,9 @@ public class MgmtDownloadArtifactResource implements MgmtDownloadArtifactRestApi
@Autowired
private ArtifactManagement artifactManagement;
+ @Autowired
+ private RequestResponseContextHolder requestResponseContextHolder;
+
/**
* Handles the GET request for downloading an artifact.
*
@@ -55,8 +61,7 @@ public class MgmtDownloadArtifactResource implements MgmtDownloadArtifactRestApi
@Override
@ResponseBody
public ResponseEntity downloadArtifact(@PathVariable("softwareModuleId") final Long softwareModuleId,
- @PathVariable("artifactId") final Long artifactId, final HttpServletResponse servletResponse,
- final HttpServletRequest request) {
+ @PathVariable("artifactId") final Long artifactId) {
final SoftwareModule module = findSoftwareModuleWithExceptionIfNotFound(softwareModuleId, artifactId);
if (null == module || !module.getLocalArtifact(artifactId).isPresent()) {
@@ -65,13 +70,14 @@ public class MgmtDownloadArtifactResource implements MgmtDownloadArtifactRestApi
final LocalArtifact artifact = module.getLocalArtifact(artifactId).get();
final DbArtifact file = artifactManagement.loadLocalArtifactBinary(artifact);
-
+ final HttpServletRequest request = requestResponseContextHolder.getHttpServletRequest();
final String ifMatch = request.getHeader("If-Match");
if (ifMatch != null && !RestResourceConversionHelper.matchesHttpHeader(ifMatch, artifact.getSha1Hash())) {
return new ResponseEntity<>(HttpStatus.PRECONDITION_FAILED);
}
- return RestResourceConversionHelper.writeFileResponse(artifact, servletResponse, request, file);
+ return RestResourceConversionHelper.writeFileResponse(artifact,
+ requestResponseContextHolder.getHttpServletResponse(), request, file);
}
diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java
index 38b4ace75..5ca100ca9 100644
--- a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java
+++ b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleMapper.java
@@ -145,8 +145,8 @@ public final class MgmtSoftwareModuleMapper {
response.add(linkTo(methodOn(MgmtSoftwareModuleRestApi.class).getSoftwareModule(response.getModuleId()))
.withRel("self"));
- response.add(linkTo(
- methodOn(MgmtSoftwareModuleTypeRestApi.class).getSoftwareModuleType(baseSofwareModule.getType().getId()))
+ response.add(linkTo(methodOn(MgmtSoftwareModuleTypeRestApi.class)
+ .getSoftwareModuleType(baseSofwareModule.getType().getId()))
.withRel(MgmtRestConstants.SOFTWAREMODULE_V1_TYPE));
response.add(linkTo(methodOn(MgmtSoftwareModuleResource.class).getMetadata(response.getModuleId(),
@@ -176,13 +176,12 @@ public final class MgmtSoftwareModuleMapper {
MgmtRestModelMapper.mapBaseToBase(artifactRest, artifact);
- artifactRest.add(linkTo(methodOn(MgmtSoftwareModuleRestApi.class).getArtifact(artifact.getSoftwareModule().getId(),
- artifact.getId())).withRel("self"));
+ artifactRest.add(linkTo(methodOn(MgmtSoftwareModuleRestApi.class)
+ .getArtifact(artifact.getSoftwareModule().getId(), artifact.getId())).withRel("self"));
if (artifact instanceof LocalArtifact) {
artifactRest.add(linkTo(methodOn(MgmtDownloadArtifactResource.class)
- .downloadArtifact(artifact.getSoftwareModule().getId(), artifact.getId(), null, null))
- .withRel("download"));
+ .downloadArtifact(artifact.getSoftwareModule().getId(), artifact.getId())).withRel("download"));
}
return artifactRest;
diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FilterHttpResponse.java b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FilterHttpResponse.java
new file mode 100644
index 000000000..7620e7404
--- /dev/null
+++ b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FilterHttpResponse.java
@@ -0,0 +1,54 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.rest.util;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Filter is needed to autowire the {@link HttpServletResponse}.
+ *
+ */
+public class FilterHttpResponse implements Filter {
+
+ private ThreadLocal threadLocalResponse = new ThreadLocal<>();
+
+ @Override
+ public void init(final FilterConfig filterConfig) throws ServletException {
+ // not needed
+ }
+
+ @Override
+ public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
+ throws IOException, ServletException {
+ try {
+ threadLocalResponse.set((HttpServletResponse) response);
+ chain.doFilter(request, response);
+ } finally {
+ threadLocalResponse.remove();
+ }
+ }
+
+ public HttpServletResponse getHttpServletReponse() {
+ return threadLocalResponse.get();
+ }
+
+ @Override
+ public void destroy() {
+ threadLocalResponse = null;
+ }
+
+}
diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/HttpResponseFactoryBean.java b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/HttpResponseFactoryBean.java
new file mode 100644
index 000000000..6df7987e6
--- /dev/null
+++ b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/HttpResponseFactoryBean.java
@@ -0,0 +1,55 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.rest.util;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.NamedBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+/**
+ *
+ * Factory bean to autowire the {@link HttpServletResponse}.
+ *
+ */
+public class HttpResponseFactoryBean implements FactoryBean, ApplicationContextAware, NamedBean {
+
+ public static final String FACTORY_BEAN_NAME = "httpResponseFactoryBean";
+
+ private ApplicationContext applicationContext;
+
+ @Override
+ public HttpServletResponse getObject() throws Exception {
+ return applicationContext.getBean(FilterHttpResponse.class).getHttpServletReponse();
+ }
+
+ @Override
+ public Class> getObjectType() {
+ return HttpServletResponse.class;
+ }
+
+ @Override
+ public boolean isSingleton() {
+ return false;
+ }
+
+ @Override
+ public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
+ this.applicationContext = applicationContext;
+ }
+
+ @Override
+ public String getBeanName() {
+ return FACTORY_BEAN_NAME;
+ }
+
+}
diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/RequestResponseContextHolder.java b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/RequestResponseContextHolder.java
new file mode 100644
index 000000000..4c2dc5c5a
--- /dev/null
+++ b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/RequestResponseContextHolder.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright (c) 2011-2016 Bosch Software Innovations GmbH, Germany. All rights reserved.
+ */
+package org.eclipse.hawkbit.rest.util;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+public class RequestResponseContextHolder {
+
+ @Autowired
+ private HttpServletRequest httpServletRequest;
+
+ @Resource(name = HttpResponseFactoryBean.FACTORY_BEAN_NAME)
+ private HttpServletResponse httpServletResponse;
+
+ public HttpServletRequest getHttpServletRequest() {
+ return httpServletRequest;
+ }
+
+ public HttpServletResponse getHttpServletResponse() {
+ return httpServletResponse;
+ }
+}