Spring expression fails after upgrade to SpringBoot 2.2 - spring

I had an application which was on SpringBoot 1.5.9. I recently upgraded to SpringBoot 2.2. I had a bunch of issues which I fixed, and now the app starts up without errors.
However, I have a #PreAuthorize on my controller methods which seems to be failing:
#PreAuthorize("not #appConfig.getSecEnabled() or hasRole('ROLE')") public void someMethod() {}
java.lang.IllegalArgumentException: Failed to evaluate expression 'not #appConfig.getSecEnabled() or hasRole('ROLE')'
What has changed in 2.2 that could cause this?

Related

SpringBoot not resolving devtools properties in tests

I'm using spring-boot-devtools with my SpringBoot application (2.2.8) to store secrets outside of my repository. This works for the running application, but integration tests fail with Unexpected exception during bean creation; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'secret.key' in value "${secret.key}".
SecretController.kt
#RestController
class SecretController(
#Value("\${secret.key}") private val secret: String
) {
#GetMapping("/secret")
fun secret(): String {
return secret
}
}
.spring-boot-devtools.properties
secret.key: secret-asdf
In an older application (SpringBoot 2.1) this works fine. I know they changed the path with SpringBoot 2.2, but kept the old path as backwards compatibility - I tried both without success. I also upgraded to 2.3.1, but this does not help either.
Any ideas on how to read properties in integration tests with SpringBoot >= 2.2?
This isn't a bug but a conscious change, see https://github.com/spring-projects/spring-boot/issues/5307
You shouldn't rely on devtools to configure your tests this way.

Spring Boot 2 controller returns a callable but http response remains empty

I'm in the process of migrating a Spring Boot 1.5 project to Spring Boot 2.1.8 (JDK 1.8, Kotlin 1.3.50).
I have a few controllers whose methods look like:
#PostMapping("post")
fun post(#RequestBody input: String): Callable<JsonNode> {
return Callable {
requestAsJson(input)
}
}
This works well in Spring Boot 1.5, without any further configuration. However with Spring Boot 2.1.8, the call does not fail but the HTTP response remains empty.
When I use start.spring.io to generate a minimalistic example, it works fine, so I guess that there is something wrong in my configuration.
When I enable debug traces for the Spring MVC, the final trace I get is:
[nio-8080-exec-3] m.m.a.RequestResponseBodyMethodProcessor : Writing [{"data":{"...
[nio-8080-exec-3] o.s.web.servlet.DispatcherServlet : Exiting from "ASYNC" dispatch, status 200
So this looks fine to me, but still no response is received (using Curl or Postman to test).
I'm a bit at a loss now, since it was working like a charm in Spring Boot 1.5 and I'm trying to get a hint on how to get out of this issue.
Thanks for any help,
Damien
I had declared a ShallowEtagHeaderFilter bean the following way in my WebMvcConfigurer:
#Bean
fun shallowEtagHeaderFilter(): ShallowEtagHeaderFilter {
return ShallowEtagHeaderFilter()
}
While this was working fine in Spring Boot 1.5, this causes the controller async methods (returning a Callable) to not return any content any longer. Removing this bean for Spring Boot 2.1 restores a normal behavior.
I still need to seek a way to have my e-tag, but for now, this solves the present issue.

Spring MVC 4 REST with protocol buffers not working

I am trying to use Spring MVC 4's Rest templates to support google protocol buffers as message format. I have am following this post on Spring framework blog
spring-mvc-google-protocol-buffers
I checked out the sourceCode trying to implement it in my environment.
I have two issues- I cannot get it to compile when I turn Java.version to 1.6 and i cannot get it to work as a webapp (don't know what
will be the context-root of the converted war file)
-Details-
I have a requirement to make this code work as a web-app and deploy on java6 container (weblogic 10.3.6 -servlet 2.5 compliant)
So i changed the java 8 features from the codebase to make it Java 6 compatible.
The only problem is when I change the pom.xml's following section
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>demo.DemoApplication</start-class>
<java.version>1.8</java.version>
</properties>
to change the java.version to 1.6 value, then try to do mvn clean install , the DemoApplicationTests class fails to compile with this error.
-google-protocol-buffers-master\src\test\java\demo\DemoApplicationTests.java:28: cannot find symbol
[ERROR] symbol : constructor RestTemplate(java.util.List<org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter>) is not defined
[ERROR] location: class org.springframework.web.client.RestTemplate
The following link shows that Spring codebase normally doesn't have any Java 8 specific source code so not sure why this code only compiles in Java 8
https://spring.io/blog/2015/04/03/how-spring-achieves-compatibility-with-java-6-7-and-8
--------------------------------------------------------------------------------
The following link shows how to convert a spring boot application to a WAR app.
I did change the pom.xml packaging option to war.
The code gets build by mvn clean install without issues and the .war file gets generated.
But there's no web.xml - so i cannot tell what will be the context-root of the deployed web app.
I either way deployed the webapp on weblogic 10.3.6 ( which is java 6 compatible)
and it deployed fine.
But when I run the DemoApplicationTests (that I have changed to point straight to the URL
using this call (got the context-root from the weblogic console by clicking on the deployed web app)
ResponseEntity<CustomerProtos.Customer> customer = restTemplate.getForEntity(
"http://127.0.0.1:7001/demo-0.0.1-SNAPSHOT/customers/2", CustomerProtos.Customer.class);
I keep getting 404 not found error.
I have put up my changed code here.
https://github.com/robinbajaj123/spring-and-google-protocol-buffers
Your feedback will be appreciated.
You'd need to convert the Spring Boot app to also be a valid Servlet application. If you were using Servlet 3 or later and chose a .war-based deployment from start.spring.io you'd get a ServletIntializer which is a Java class that is the programmatic equivalent of web.xml. Since you're using 2.5, not 3.0, you need an explicit web.xml. You might check out this sample on how to get a Boot app hoisted up in a Servlet 2.5 environment, though using Servlet 2.5 is not recommended!. It's worth mentioning that Servlet 3.0 support was introduced in 2009..
Finally, this code uses Java 8 lambdas. You'll need to replace the lambdas with Java 6-equivalent code. One example I see is:
#Bean
CustomerRepository customerRepository() {
...
The last line in the #Bean definition returns a lambda: customers::get. Replace it with:
final Map<Integer, CustomerProtos.Customer> customers =
new ConcurrentHashMap<Integer, CustomerProtos.Customer>();
return new CustomerRepository() {
public CustomerProtos.Customer findById(int id) {
return customers.get( id) ;
}
};
Similarly, replace the forEach method in the List w/ an old-school for-in loop:
for (CustomerProtos.Customer c : Arrays.asList( ... )) {
customers.put(c.getId(), c);
}

Spring on WebSphere 8: Quartz job with web service call throws JAXBException "<class> is not known to this context"

I'm facing a JAXBException " is not known to this context" when calling a web service from within a job controlled by Quartz on Spring:
javax.xml.ws.WebServiceException: javax.xml.bind.JAXBException: com.xxxx.yyyy.zzzz.ImageMetaData is not known to this context
at org.apache.axis2.jaxws.ExceptionFactory.createWebServiceException(ExceptionFactory.java:175)
at org.apache.axis2.jaxws.ExceptionFactory.makeWebServiceException(ExceptionFactory.java:70)
at org.apache.axis2.jaxws.ExceptionFactory.makeWebServiceException(ExceptionFactory.java:128)
at org.apache.axis2.jaxws.marshaller.impl.alt.DocLitWrappedMinimalMethodMarshaller.demarshalResponse(DocLitWrappedMinimalMethodMarshaller.java:624)
at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.createResponse(JAXWSProxyHandler.java:593)
at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.invokeSEIMethod(JAXWSProxyHandler.java:432)
at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.invoke(JAXWSProxyHandler.java:213)
at com.sun.proxy.$Proxy299.findAllImageMetaData(Unknown Source)
I'm having a Spring 3.2.4 Java EE application with JSF running on IBM WebSphere v8.
When calling a specific web service from the JSF part of the application (i.e. from an action or a service), everything's ok.
The exception occurs only when the call is done from within a Quartz/Spring triggered job.
Executing exacty the same job code from the action does not result in an exception.
I tried a lot of different things like using a corresponding #XmlSeeAlso annotation in the JAXB generated classes but even using the annotation in the webservice interface itself does not solve the issue.
I also updated the Spring and Quartz libraries to more recent versions but this didn't help.
Anyone any idea?
I've finally solved the issue.
After much analysis I encountered the following issue in the Spring framework:
https://jira.spring.io/i#browse/SPR-11125
When a job is triggered via Spring/Quartz on WebSphere, the wrong ContextClassLoader is set.
This may cause many different problems - among them is the JAXBException as described.
The Spring bug is still open - so as a workaround I had to overwrite the context class loader of the current thread by the correct one:
ClassLoader cl = invoiceService.getClass().getClassLoader();
Thread.currentThread().setContextClassLoader(cl);
The correct class loader can be simply retrieved by a class that has been loaded by the container. Using this class loader as the context class loader for the current thread solved my issue.

How to use Spring Roo with Apache Wicket?

I have a persistence layer (JPA entity objects) created and managed by Roo. It is in its own project, builds to a jar, and I have used it with a separate Spring MVC 3 web application.
I'd like to use this same Roo persistence project in another web application powered by Apache Wicket. I have seen a couple of the Roo add-ons made for Wicket, but none of them even compile (I'm not the only one to have the issue).
The problem I am encountering is that whenever I try to call one of my Roo entities from within a Wicket Page or component, I get the following exception:
Caused by: java.lang.IllegalStateException: Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)
at com.x.domain.UserAccount_Roo_Entity.ajc$interMethod$com_x_domain_UserAccount_Roo_Entity$com_x_domain_UserAccount$entityManager(UserAccount_Roo_Entity.aj:91)
at com.x.domain.UserAccount.entityManager(UserAccount.java:1)
I have configured my application following the Spring+Wicket wiki here: https://cwiki.apache.org/WICKET/spring.html
Does anyone know the 1,2,3 steps to set up a Wicket application to utilize Spring Roo entities? Any help is appreciated. Thanks!
I found this in google code, sounds like its doing exactly what you want http://code.google.com/p/spring-roo-wicket-addon/
I found the solution to my problem. When I ran my wicket webapp using the Maven jetty:run goal, it worked. However, I was trying to start Jetty via Java code:
public class Start {
public static void main(String[] args) throws Exception {
Server server = new Server();
SocketConnector connector = new SocketConnector();
server.start();
}
}
I was not loading the Spring ApplicationContext in this "Start" class. Once I modified this class to load the Spring application context, it worked

Resources