#ConfigurationProperties object returned null in spring boot application - spring-boot

I have a config object which is mapped to the config file as below:
#Data
#Component
#ConfigurationProperties("app.cors")
public class DomainProperties {
private Map<String, String> domainMap;
}
and my application.properties config file looks like:
app.cors.domainMap.local=localhost:8080
app.cors.domainMap.onlive=test.com
I am trying to read the values in the domainMap from the above properties file, to set them as Access-Control-Allow-Origin headers for the response of my application. What I did so far is:
public class HeaderInterceptor extends HandlerInterceptorAdapter {
#Autowired
private DomainProperties domainProperties;
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
List<String> domainList= domainProperties.getDomainMap().values().stream().collect(Collectors.toList());
domainList.stream().forEach(domain -> response.addHeader("Access-Control-Allow-Origin", domain));
return super.preHandle(request, response, handler);
}
but the problem is I received back a null domainProperties object, therefore a NullPointerException is thrown here.
Can anyone explain me why did I get a null domainProperties object here? and how to resolve this problem. Thank you in advanced!

Related

Properties in application.properties not getting loaded in Filter class

I am trying to read the value from application.properties in one of the util library Filter we write.
My code is as below.
public class AuthorizationFilter extends GenericFilterBean
{
#Value ("${application.identifier}")
private String appId;
...
}
However the value appId is not read from application.properties though it is defined.
The issue occurs only with Filter classes.
Any pointers on how to fix this?
Like #M.Deinum said , If you let spring-boot manage the life cycle of the filter bean, then you will be able use the #Value annotation :
#Component
#Order(1)
public class CustomFilter implements Filter {
#Value ("${application.identifier}")
private String appId;
#Override
public void doFilter
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
LOG.info(
"Starting for req : {}",
req.getRequestURI());
chain.doFilter(request, response);
LOG.info(
"Anything");
}
// other methods
}
Keep in mind that if you provide your filter this way , you won't have to register it manually and if you want it to work for a particular url by registering it manually remember to remove the #Component annotation so that spring-boot won't take it up automatically.
Let the spring manage your filter class. You can register in your filter class like below :
#Bean
public FilterRegistrationBean registerFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(this);
registration.addUrlPatterns("/*");
return registration;
}

Apache camel dynamic routing

I have following Apache camel rest service(/sales) that internally calls another rest service(/getOrders) and get list of objects. Am able to print JSON response in the processor but getting java objects in response while trying from postman. Could anyone pls help me to resolve the issue. Attaching the response log for ref..
#Component
public class ApplicationResource extends RouteBuilder {
#Autowired
private OrderService service;
#BeanInject
private OrderProcessor processor;
#Override
public void configure() throws Exception {
restConfiguration().component("servlet").port(9090).host("localhost");
rest().get("/getOrders").produces(MediaType.APPLICATION_JSON_VALUE).route().setBody(() -> service.getOrders());
rest().get("/sales").produces(MediaType.APPLICATION_JSON_VALUE).route()
.setHeader(Exchange.CONTENT_TYPE, constant("application/json"))
.toD("http://localhost:9090/getOrders?bridgeEndpoint=true").convertBodyTo(String.class).marshal()
.json(JsonLibrary.Jackson, Order.class).to("log:foo?showHeaders=true");;
;
}
}
You should remove the last .endRest() on "direct:bye" route.
I think you get the rest response before calling your Processor.
This works for me.
First, I needed to set the bindingMode as RestBindingMode.json in the restConfiguration.
Secondly, instead of marshal(), you need to use unmarshal().
Third, since you are returning a list of orders, .json(JsonLibrary.Jackson, Order.class) will not be sufficient to unmarshal the list of orders. You need to use a custom format which will be able to unmarshal the list of orders into a json array. This you need to do using JacksonDataFormat format = new ListJacksonDataFormat(Order.class);
#Override
public void configure() {
JacksonDataFormat format = new ListJacksonDataFormat(Order.class);
restConfiguration().component("servlet").port(9090).host(localhost).bindingMode(RestBindingMode.json);
rest()
.get("/getOrders")
.produces(MediaType.APPLICATION_JSON_VALUE)
.route()
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
exchange.getMessage().setBody(service.getOrders());
}})
.to("log:getOrders?showHeaders=true&showBody=true");
rest()
.get("/sales")
.produces(MediaType.APPLICATION_JSON_VALUE)
.route()
.setHeader(Exchange.CONTENT_TYPE, constant("application/json"))
.toD("http://localhost:9090/getOrders?bridgeEndpoint=true")
.unmarshal(format)
.to("log:sales?showHeaders=true&showBody=true");
}
Solvedddd !!! i did two things as follows,May be use full for some one
1,bindingMode(RestBindingMode.auto) - RestBindingMode changes to auto
from json
2, Added this in the main
service(/getOrders).marshal().json(JsonLibrary.Jackson);
#Component
public class ApplicationResource extends RouteBuilder {
#Autowired
private OrderService service;
#BeanInject
private OrderProcessor processor;
#Override
public void configure() throws Exception {
restConfiguration().component("servlet").port(9090).host("localhost").bindingMode(RestBindingMode.auto);
rest().get("/getOrders").produces(MediaType.APPLICATION_JSON_VALUE).route().setBody(() -> service.getOrders())
.marshal().json(JsonLibrary.Jackson);
rest().get("/sales").produces(MediaType.APPLICATION_JSON_VALUE).route()
.setHeader(Exchange.CONTENT_TYPE, constant("application/json"))
.toD("http://localhost:9090/getOrders?bridgeEndpoint=true").convertBodyTo(String.class)
.log("body = ${body}");
;
;
}
}

Controller Advice not handling FileTooLargeException by exceuting method annotated with FileTooLargeException

My rest controller contains following post mapping :
#PostMapping
public ResponseEntity<RespDTO> uploadDocument(#ModelAttribute #Valid RequestDTO requestDTO,#RequestParam(value = "fileContent") MultipartFile fileContent) throws ServiceException, URISyntaxException { }
ServiceExceptionn is a custom exception specific to my application.
The controller advice looks like below:
#ControllerAdvice
public class ExceptionTranslator implements ProblemHandling, SecurityAdviceTrait {
#Override
public ResponseEntity process(#Nullable ResponseEntity<Problem> entity, NativeWebRequest request) {
}
#ExceptionHandler(FileTooLargeException.class)
public ResponseEntity<ResponseDTO> handleFileTooLargeException(FileTooLargeException ex, #Nonnull NativeWebRequest request){
}
}
application.yml contains below property :
spring:
servlet:
multipart:
max-file-size: 2MB
If I call the rest api using file having size greater than 2MB, then I am getting below exception:
io.undertow.server.handlers.form.MultiPartParserDefinition$FileTooLargeException: UT000054: The maximum size 5242880 for an individual file in a multipart request was exceeded
Issue that I am facing here is:
the controller advice is not working as per expectation.
handleFileTooLargeException - this method must get executed because it is annotated with ExceptionHandler mentioned with the specific exception type.
But instead of that, the control goes into process method of the controller advice.
Not able to understand what I am missing here.
You need ExceptionTranslator class to extend ResponseEntityExceptionHandler class to enable methods with #ExceptionHandler annotation

Add more field into header using interceptor of spring boot not work

I'm using spring boot.
I want to add a field into header of every response. So that, i using interceptor. The code is:
#Component
public class ApiVersionInterceptor extends HandlerInterceptorAdapter{
private final Logger log = LoggerFactory.getLogger(ApiVersionInterceptor.class);
#Autowired
private Environment environment;
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception arg3) throws Exception {
String apiVersion = environment.getProperty(ApiVersion.VERSION_KEY.getKey());
log.debug("api-version:"+apiVersion);
response.addHeader("Api-Version", apiVersion);
}
}
And the configuration is:
#Configuration
public class InterceptorsConfiguration extends WebMvcConfigurerAdapter {
#Autowired
private ApiVersionInterceptor apiVersionInterceptor;
/**
* Add interceptor
*/
#Override
public void addInterceptors(final InterceptorRegistry registry) {
//Add api-version field to header of response
registry.addInterceptor(apiVersionInterceptor);
}
}
To make sure this snipped code is run because of:
2017-12-06 02:35:10,392 DEBUG [] [http-nio-8080-exec-7] ApiVersionInterceptor: api-version:1.9.0
But i don't understand, i don't see this field in the header of any response.
Update
My app use Restful webservice, so don't have view phase.
Thanks for help.
You should add header in a earlier phase, override the preHandle method in your ApiVersionInterceptor. Because in afterCompletion response is already committed and skip header changes.

How can I log the JSON response of Spring 3 controllers with #ResponseBody in a HandlerInterceptorAdapter?

I have controllers that return JSON to the client. The controllers methods are marked using mvc annotation such as:
#RequestMapping("/delete.me")
public #ResponseBody Map<String, Object> delete(HttpServletRequest request, #RequestParam("ids[]") Integer[] ids) {
Spring knows to return JSON since Jackson is on the class path and the client is requesting a JSON response. I would like to log the response of these requests and all other controllers. In the past I have used an interceptor to do this. However, I got the response body from the ModelAndView. How can I get the response body in the inteceptor now that I'm using #ResponseBody? Specifically, how can I get the response body in this method?
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
You can log everything by using CustomizableTraceInterceptor
you can either set it in your application context xml config and use AOP: (log level Trace)
<bean id="customizableTraceInterceptor"
class="org.springframework.aop.interceptor.CustomizableTraceInterceptor">
<property name="exitMessage" value="Leaving $[methodName](): $[returnValue]" />
</bean>
or you can completly customize it by implementing it in Java and use the method setExitMessage():
public class TraceInterceptor extends CustomizableTraceInterceptor {
private Logger log = LoggerFactory.getLogger("blabla");
#Override
protected void writeToLog(Log logger, String message, Throwable ex) {
//Write debug info when exception is thrown
if (ex != null) {
log.debug(message, ex);
}
....
}
#Override
protected boolean isInterceptorEnabled(MethodInvocation invocation, Log logger) {
return true;
}
#Override
public void setExitMessage(String exitMessage) {
.... //Use PlaceHolders
}
}
and use the placeholders such as '$[returnValue]'. You can find the complete list in the spring api documentation.
EDIT: Also, if you want to get the value of your #ResponseBody in another interceptor, I think it's not possible until version > 3.1.1. Check this issue: https://jira.springsource.org/browse/SPR-9226

Resources