java.lang.NoClassDefFoundError Could not initialize class org.springframework.mock.web.MockServletContext - spring

We are using Spring-test-4.0.6 jar in test scope in our project. Under same project we also have javaee-6.0 dependency in provided scope.
I am getting this error in test case
Could not initialize class org.springframework.mock.web.MockServletContext at com.sample.TestWebDOMConfiguratorMultiple.setUp(TestWebDOMConfiguratorMultiple.java:77)
Surprisingly replacing Javaee-6.0 dependency with servlet-api-3.0.1 resolves this issue.
Note: Spring-4.0.6 pom has compile time optional dependency on servlet-api-3.0.1.
Question is why is it working with servlet-3.0.1 and not with javaee 6.0 as we are trying
to replace servlet-api-3.0.1 with javaee-6.0.
Thanks in advance.

Without knowing the exact artifact that you are referring to as javaee-6.0 and without being able to see the full stack trace, it appears that your javaee-6.0 dependency contains Servlet API 3.0; whereas, spring-test-4.0.6.RELEASE explicitly requires Servlet API 3.0.1.
So that is likely the source of your problem.
Regards,
Sam

Related

Opening bean declared in Configuration class

Recently I encountered strange problem with Spring, Kotlin and Spock. I have very simple project (spring-boot, spring-web). I have one Controller with few Beans injected to this Controller. Everything works just fine. Problem is in test. I am not able to mock any of those Beans. kotlin-spring/kotlin-allopen does not add open signature to beans defined in Configuration class. On the other hand if I change this declaration to #Component everything works fine.
Here is my build.gradle.kts plugin listing
plugins {
id("idea")
id("groovy")
id("maven-publish")
id("org.springframework.cloud.contract") version "2.2.5.RELEASE"
id("org.springframework.boot") version "2.4.1"
id("io.spring.dependency-management") version "1.0.10.RELEASE"
kotlin("jvm") version "1.4.21"
kotlin("plugin.spring") version "1.4.21"
kotlin("plugin.allopen") version "1.4.21"
}
This is error message:
Caused by: org.spockframework.mock.CannotCreateMockException: Cannot create mock for class *** because Java mocks cannot mock final classes. If the code under test is written in Groovy, use a Groovy mock.
I know that it says that I can use GroovyMock but I wanted to design my base class in test and I wanted to use #TestConfiguration class. So to mock those classes I wanted to use DetachedMockFactory.
Is there a way to configure Spock to be able to mock final classes from Kotlin? Or is there a way to tell kotlin-spring/kotlin-allopen to open classes defined as beans in Configuration class?
Edit:
My example project is here:
https://github.com/czyzniek/bank/tree/with-spock
I cannot help you fix the spock-mockable problem, maybe you want to ask the author for help. Recently I fixed a Maven issue in that project already, but now it seems like there is a ByteBuddy issue, trying to redefine an already loaded class which is impossible in the JVM. I am sure the maintainer can help you with that.
Meanwhile, like I suggested in a previous comment, switching to Sarek solves the problem, though. I created a corresponding pull request for you.
For now it uses the full Sarek agent, which is the default. If you add sarek-unfinal as a dependency instead of sarek and also make sure that you set the system property dev.sarek.agent.type=unfinal in your Gradle configuration for Spock tests, you can use the smaller unfinal agent without the rest of the Sarek functionality instead. As a Gradle noob I do not know how to configure that, though.
Update: There is no more need for the additional system property mentioned above. The latest Sarek snapshot auto-detects the unfinal agent (or any other of the 4 types of Sarek agents) when it is on the class path. I know you have decided to use spock-mockable, but I want to keep this answer up to date for reference. See this diff for what the pull request would look like now, especially this simple commit.
Please let me know if you have any issues using the snapshot version for now. If this is a commercial project and you need to build a release in which snapshot versions are forbidden at some point, I can publish an 1.0 or maybe a 0.8 or whatever on Maven Central. For now I just added the Maven Central snapshot repository (Sonatype OSS) to your build.
Thanks for help everybody! #kriegaex your solution works like a charm, thanks for that!
Regarding spock-mockable, I talked with author of this library and he figured out why spock-mockable could not work with my setup (GH issue). It was because of spock-spring extension. The root cause is that spock-spring extension was loaded before spock-mockable. When Spring/Spock wanted to create mocks from #TestConfiguration class it couldn't, because kotlin-spring plugin does not open classes declared as beans in a #Configuration class and spock-mockable was not loaded at this time. joke changed the way his extension is loaded, so right now both solutions spock-mockable and sarek work.
I believe that concludes my problem ;)

Spring Resource Loading

Can anyone explain how Spring decides where to look for resources when one uses the ResourceLoader.getResource(...) method?
I am having a problem with a multi-module maven application built using Spring Boot whereby in my integration tests my code is able to find resources using resourceLoader.getResource("templates/") or even resourceLoader.getResource("classpath:templates/"). So far so good...
However, when the module is eventually packaged into the executable JAR and run with embedded Tomcat the resources can no longer be resolved. I also tried resourceLoader.getResource("classpath*:templates/") with no success.
What I find concerning is that when I add a logging statement to output the URL being used in the search i get a path to one of the other modules in the project (not the one that actually contains the resource in question). E.g: jar:file:/Users/david/exmaple/target/spring-boot-0.0.1-SNAPSHOT.jar!/lib/module1-0.0.1-SNAPSHOT.jar!/templates/ whereas I believe the resource is in jar:file:/Users/david/exmaple/target/spring-boot-0.0.1-SNAPSHOT.jar!/lib/module2-0.0.1-SNAPSHOT.jar!/templates/
The resource loader was obtained from an Autowired constructor param.
Thanks in advance for any hints.
Edit
Just in case it isn't clear or is of importance, my integration tests for the module in question aren't aware of the other module. I have module1, module2 and a spring-boot module which has dependencies on module1 & module2. Essentially, when I run the integration tests for module 2 the classpath isn't aware of module1 - so I suspect that this has something to do with why it works in the tests.
When you use classpath: or classpath*: prefix, internally, this essentially happens via a ClassLoader.getResources(…​) call in spring.
The wildcard classpath relies on the getResources() method of the underlying classloader. As most application servers nowadays supply their own classloader implementation, the behavior might differ especially when dealing with jar files. A simple test to check if classpath* works is to use the classloader to load a file from within a jar on the classpath: getClass().getClassLoader().getResources("<someFileInsideTheJar>"). Try this test with files that have the same name but are placed inside two different locations. In case an inappropriate result is returned, check the application server documentation for settings that might affect the classloader behavior.
Do not use classpath: form as you have multiple classloader locations of templates/ .
Refer to: resources-classpath-wildcards

Spring Boot v1.2 AbstractMethodError due to RepositoryInformation

Im building an application based on Spring Boot v1.2. While my application boots successfully and executes well (so far.. ), I'm unable to test using the spring boot framework because of an AbstractMethodError.
The last few lines of the trace are as below
Caused by: java.lang.AbstractMethodError: org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor.postProcess(Lorg/springframework/aop/framework/ProxyFactory;Lorg/springframework/data/repository/core/RepositoryInformation;)V
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:185)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:239)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:225)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:84)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1627)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1564)
... 55 more
To analyze the above error, I checked the jar files from classpath involving the above classes. So the info is available as below
jar:file:/C:/rearch/intellij-workspace/springbootproj/lib/spring-aop-4.1.2.RELEASE.jar!/org/springframework/aop/framework/ProxyFactory.class
jar:file:/C:/rearch/mavenrepo/org/springframework/data/spring-data-commons/1.9.1.RELEASE/spring-data-commons-1.9.1.RELEASE.jar!/org/springframework/data/repository/core/RepositoryInformation.class
jar:file:/C:/rearch/intellij-workspace/springbootproj/lib/spring-data-jpa-1.3.3.jar!/org/springframework/data/jpa/repository/support/LockModeRepositoryPostProcessor.class
jar:file:/C:/rearch/intellij-workspace/springbootproj/lib/spring-test-4.1.2.RELEASE.jar!/org/springframework/test/context/support/DependencyInjectionTestExecutionListener.class
I'm not exactly sure on why spring-data-commons is coming up from maven repostory folder, while the others are being served from the project library.
While I debug that, I meanwhile need your help in figuring out the version compatibility between the above libraries.
I wasnt able to exactly pin point on what exactly is causing the error. Please help!
Thanks
The issue was with the intellij configuration of libraries which conflicts with Spring boot application. I manually replaced the required libraries from Maven repository and that worked out for me.
Per request from Elron..
Open the project folder in explorer and verify if the third party library versions in your project matches the ones you actually expect it to be. If something doesnt match, just replace the file with the one you expect it to be. In my case, since I use Maven, I didnt see a need for explicitly saving those libraries in a new lib folder under the project. So, I just deleted all of the files inside the lib folder and things started working again.
For fix this error, change the spring-data-jpa version to 1.5.0.RELEASE
I have faced this issue .
Get rid of spring-data-commons and change spring-data-jpa version to 1.9.0.RELEASE.
For more details , please follow this link :-
Spring Data Rest PagingAndSortingRepository AbstractMethodError (RepositoryFactorySupport)

glassfish 4 and jersey-media-multipart 2 don't work with beans.xml

I am using glassfish 4 to build some restful apps using the standard Java 7EE stack recently released.
My basic restful service works fine, but now I want to handle incoming file uploads which use the multipart mime type within the same service.
I found a POC jersey maven example (multipart-webapp) referred to in the https://jersey.java.net/documentation/latest/user-guide.html
and this deploys and works fine.
However, as soon as I build on this framework to include dependency injection, and in particular, as soon as I create a beans.xml file ( even an empty one ), I get all sorts of errors like:
SEVERE: Exception while loading the app : CDI deployment failure:WELD-001408 Unsatisfied dependencies for type [Providers] with qualifiers [#Default] at injection point [[BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedConstructor] #Inject public org.glassfish.jersey.media.multipart.internal.MultiPartReaderServerSide(#Context Providers, Provider)]
I've tried using the new bean-discovery-mode attribute set to all or none in my beans.xml file but it makes no difference.
Is this a bug in Glassfish or Jersey, or are they currently incompatible even though Glassfish includes all the jars involved, or am I doing something really silly?
It turns out that the error messages and beans.xml behaviour are red herrings. To help anyone with the same problem, this is what you need to do to use multipart mime inside a restful interface on glassfish.
Make sure the library is added only at compile time. If you use netbeans, this means adding multipart-mime-xxx.jar from the glassfish/modules directory as a library, but unclicking the 'package' button, so it is not included in the war package ( since it's already inside glassfish anyway.
If you are using maven, you achieve the same result by using a provided tag inside the dependency:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<scope>provided</scope>
</dependency>
If you are using a restful template generated by netbeans as your starting point, you will have a file called application-config.java which has been generated for you. Add the line:
resources.add(MultiPartFeature.class);
immediately above the line
addRestResourceClasses(resources);
Now you should find that you can safely use the various annotations for multipart mime in jersey.

Maven Dependencies for JBoss 7.1 EJB Client

I wanted to implement an EJB client for JBoss 7.1 following this tutorial
http://middlewaremagic.com/jboss/?p=1177#comments which is based on the JBoss tutorial:
https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+client+using+JNDI
I already tried the troubleshooting tips there, but still I get an exception:
javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
Did anyone else encounter this type of problem and knows which jars (or better Maven dependencies) are needed on the classpath?
Best regards,
Helge
Have you referred to the ejb-remote quick start ? https://github.com/jboss-jdf/jboss-as-quickstart/tree/master/ejb-remote
That quick start contains the two Maven projects that are referenced in the jboss.org doc and have all the required dependencies.

Resources