How to remove NullPointerException from JSR 330 Spring application - spring

I am implementing Spring+JSF application following the guidlines of http://www.mkyong.com/jsf2/jsf-2-0-spring-integration-example/ but I am using the latest Spring version (i.e. 3.x, it already contains the JSR 330 implementation, according to the documentation, so this should not be an issue) and my own classes, that is the difference from the mentioned example.
I am stuck with NullPointerException that indicates that the bean (that acts as JSF managed) bean has not received injection of the instance of Spring bean. All the beans use JSR 330 annotations at appropriate places (#Named, #Inject) and the interfaces of the beans and the variables (under #Inject annotation) follow the usual naming patterns...
So - how to debug this situation. E.g. is there way to see all the beans that sit into the Spring application context. E.g. so we can determine that the Spring context is not initialized appropriately. Maybe there are other methods how to see what is happening in app (debug injection)?

Spring supports JSR 330 annotations for dependency injection provided you have the relevant jars in your classpath.
You need to add the following jar to your application.
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
And you might get good info by enabling logging for org.springframework
Just add log4j jar and drop in this log4j.properties file in the root of the classpath.
Log4j.properties:
log4j.rootCategory=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p %c %M - %m\n
log4j.category.org.springframework=DEBUG
See also:
Documentation
beans-standard-annotations
overview-logging-log4j

Related

Spring Boot : Cannot load driver class: org.hsqldb.jdbcDriver

I have a simple Spring Boot application (generated through Spring Roo).
The database is configured as following :
spring.datasource.driver-class-name=org.hsqldb.jdbcDriver
spring.datasource.url=jdbc\:hsqldb\:mem\:PetClinic
spring.jpa.hibernate.naming.strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.messages.encoding=ISO-8859-1
spring.messages.fallback-to-system-locale=false
spring.thymeleaf.mode=html
Here are the how I declared the HSQLDB dependency :
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>provided</scope>
</dependency>
When I start the application, I get the error :
Caused by: java.lang.IllegalStateException: Cannot load driver class: org.hsqldb.jdbcDriver
at org.springframework.util.Assert.state(Assert.java:392) ~[spring-core-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.determineDriverClassName(DataSourceProperties.java:214) ~[spring-boot-autoconfigure-1.4.1.RELEASE.jar:1.4.1.RELEASE]
The Spring-boot-autoconfigure module tries to load the class with the ClassUtils utility class that loads the current context classes.
I wonder if this method works fine since I use a Tomcat container which is responsible to load the Maven dependencies ?
Why even with the JAR in the libs directory Spring is not able to find it ?
Remove <scope>provided</scope> from your pom.xml
Remove both spring.datasource.driver-class-name and spring.datasource.url properties from your application properties
Because:
when spring.datasource.url is provided the driver class name is redundant as Spring Boot will automatically attempt to load the correct driver.
since you want to use an embedded database you don't need to provide spring.datasource.url at all. Just need to have an embedded database JAR on the classpath (like HSQLDB)
Relevant docs snippet:
Spring Boot can auto-configure embedded H2, HSQL and Derby databases.
You don’t need to provide any connection URLs, simply include a build
dependency to the embedded database that you want to use.
Please read the Working with SQL databases section in of Spring Boot documentation. Everything I said is mentioned there, so you can get more detail.
I see the scope you gave is provided, <scope>provided</scope>, I don't think Tomcat provides the hsqldb.jar with it out of the box.
So try removing the provided scope.

How to inject a bean into JAX RS resource?

I am sure this is most probably a silly question but I am not familiar with JAX RS (and Jersey).
We've had a standalone Java application that basically starts a RESTful service. As part of a refactoring, we've moved this application to be just a thread within another application. That other application uses Spring beans that are defined in an application-context.xml. So, I need to inject some of those beans to the resource class (if that's the correct name for it: the one with #Path annotations, etc.). The problem is I don't know what instantiates this particular class. There is a main class of the legacy app that is creating a (jetty) Server instance with ServletContexthandler to which a ServletHolder is added to which a ResourceConfig is set. Something like that.
So, I can inject my stuff from Spring to this main class but can't see how exactly I can pass those objects to the JAX RS resource?
I am sure I miss something pretty simple.
Edit: I have added a better explanation to my problem and a solution I found below.
Jersey has integration with Spring support. For this case, there are really only two things you need to do:
Make sure you have the integration dependency. You'll also need to the commons logging, so it doesn't complain
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring4</artifactId>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
Just add a ContextLoaderListener along with a WebApplicationContext containing your Spring context configuration.
ServletContextHandler context
= new ServletContextHandler(ServletContextHandler.SESSIONS);
AnnotationConfigWebApplicationContext wac
= new AnnotationConfigWebApplicationContext();
wac.register(SpringConfig.class);
context.addEventListener(new ContextLoaderListener(wac));
Here the SpringConfig is just a "Java config" Spring configuration class. If you wanted you could use an XML application context, but the example I used in the below link uses a Java config class, but also show how to easily import an XML into the class if you just want to use your XML config. You can combine two.
That's pretty much it. Once you have this configured, you should be able to #Autowired your Spring beans into your Jersey resources.
For a complete example, check out this GitHub repo
Maybe I wasn't able to explain well my problem, so basically it was a problem of how to inject beans into JAX-RS resource classes when the actual JAX-RS app is not being instantiated through its own DI-mechanism but from somewhere else. In my case I already had a Spring container that creates those beans and there was no easy way to link the Spring's own bean application context to the JAX-RS's one. A better solution would have been the one already answered but additional problem is that our existing Spring solution is XML-based, whereas the #Injected annotation in JAX-RS won't work with it (at least that's what I've read in their documentation).
So, JAX-RS supports #Injected annotations and in order for it to know where to get bean definitions from, I had to go to the class that defines the ResourceConfig and add the following lines to it:
.register(new AbstractBinder() {
#Override
protected void configure() {
bind(beanImpl1).to(BeanInterface1.class);
bind(beanImpl2).to(BeanInterface2.class);
}
})
The actual beanImpl1 and beanImpl2 bean instances were coming through the constructor of that class, which in turn was instantiated from our Spring through the XML configuration.

Dependency injection with Spring (JSR 330 annotations) in WebSphere 7 is not working

I have an enterprise application built with Java 6, Spring Framework 3.1.2 and Mule-ESB 3.3.0, among other libraries not related to this question.
Our beans and services are all declared with #Named and #Inject JSR-330 annotations, respectively for automatic component scanning and for dependency injection (no EJBs, only service beans). When deployed into JBoss 4.2.3 (our test environment) everything works fine. However, when deployed into WebSphere 7, the JSR-330 annotations seem not to be working. The beans marked with #Named are just not detected, at all.
I can assure everything is configured right (since it is working in JBoss). Specifically, the <context:component-scan /> has the base-package attribute correctly defined and the scope-resolver attribute correctly configured to use Jsr330ScopeMetadataResolver (we tried without it too).
I am aware WebSphere 7 (7.0.0.23) may not support such kind of annotations. I am yet to test it with #Component and #Autowired Spring equivalents. Unfortunately, we would very much like to use JSR 330 annotations so our classes wouldn't directly depend on Spring, even though we're using Spring Framework under the hood.
Nevertheless, although I'd spent one full work's day looking for a definite statement that WebSphere 7 does not support JSR 330 annotations, I haven't found anything so far.
Further, I can't see why it would not work, since I'm assuming Spring Framework is the one doing all the work, through the <context:component-scan /> directive in the application-context.xml file.
Can anyone bring some light into this issue?
Is there a way to activate dependency injection via annotations in WebSphere 7?
If I switch back from the JSR 330 #Named / #Inject annotations to Spring's own #Component and #Autowired is it likely to work?
In a desperate attempt, can I extend Spring's ComponentScanBeanDefinitionParser so it will detect JSR 330 annotations even in WebSphere 7?
If nothing works, I will eventually fall back to plain XML configuration. That is highly undesirable, however, because there will be hundreds of beans to be manually configured in the XML.
WebSphere 8 seems to be the correct version to use; it supports EE6 (WebSphere 7 is EE5), which in turn contains CDI 1.0 (hence JSR 299).
Below is a snippet from DeveloperWorks that summarises relationship between WebSphere versions, JSR 299 and JSR 300
Dependency injection is a technology that has surfaced in various
implementations many times before making it into the Java EE world.
The Spring Framework and the Google Guice library are popular
implementations. In JSR 330, an attempt was made to include these
capabilities into the J2SE platform. JSR 299 is a specification that
used the APIs defined in JSR 330 and added more capabilities to
support Java EE needs. IBM WebSphere Application Server V8 and V8.5
(non-Liberty profiles) are fully compliant Java EE 6 containers and
implement JSR 299.
I eventually came up with a workaround by extending both Component Scan and Autowire features of Spring Framework.
First, I added an inclusion filter to the Component Scanner so that #Named annotations were also considered eligible for detection and registration to the Spring Container:
<context:component-scan base-package="com.mycompany.mysystem">
<context:include-filter type="annotation" expression="javax.inject.Named" />
</context:component-scan>
Following that, I also added a bean definition to org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcesso‌​r, extending the autowiring eligibility to #Inject annotations:
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor">
<property name="autowiredAnnotationType" value="javax.inject.Inject" />
</bean>
Initially, this worked fine as to "reactivating" the #Named and #Inject annotations. However, I still had some problems of conflicting beans on the autowire candidates resolution process. This was due to the differences in the default resolution process of Spring and of JSR-330. This was no big issue, since only a few beans fell into that scenario. They were all solved by adding some strategically placed #Qualifier annotations.
Now everything is working fine and elegantly, with few extra configurations. Nevertheless, I still don't understand why this happened. All I know is that the following 3 lines do appear when I deploy the application into JBoss 4.2.3. On the other hand, they don't appear in WebSphere:
INFO [org.springframework.context.annotation.ClassPathBeanDefinitionScanner] JSR-330 'javax.inject.Named' annotation found and supported for component scanning
and
DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] Creating instance of bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
INFO [org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor] JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
I still have no clue as to why this happens, since, as #Dreamer said, this should be a Spring's responsibility, and thus, out of WebSphere business.
If someone do have such a clue, please enlighten us. Im sure it would be wonderfully clarifying to everyone participating in this discussion.
Agree with duffymo, it should work on WS 7. As Spring is on top of Websphere so Spring annotation is out of webshere's business(sort of).
One thing you probably need to check on WS 7(even though you said every configuration is correct as it works on JBoss) is click your application -> click Class loading and update detection, make sure the Classes loaded with local class loader first (parent last) is checked. That would make the server to take your application's library come first followed by websphere's library.

Java Spring configuration and Resteasy

I am trying to integrate Resteasy and Spring; I have followed both the docs for Resteasy and this post: Inject Spring beans into RestEasy .
I have it working using #Autowire or other Spring annotations on the rest class, but I would like to do this keeping my rest classes free from spring (or DI) dependencies.
I also would like to configure spring only through java configuration. In spring configuration I added this:
<context:component-scan base-package="package.where.spring.configuration.beans.are , package.where.rest.classes.are">
<context:include-filter type="annotation" expression="javax.ws.rs.Path"/>
</context:component-scan>
and of course I have in web.xml, so that spring config is picked up by SpringContextLoaderListener:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/spring-config.xml</param-value>
</context-param>
Removing the #Autowire annotations, if I also remove the first package (where I configured the injections through Spring java config) no injection takes place and the fields remain null; if I remove the second package the urls for the rest classes are not recognized by resteasy.
I would like to configure the injections just in Spring configuration, is there a way to have resteasy recognize the paths from spring beans which are configured externally?
EDIT: I noticed that what I am trying to do works with #Provider annotated classes, given that you configure Spring correctly:
<context:component-scan base-package="my.package1 , my.package2">
<context:include-filter type="annotation" expression="javax.ws.rs.ext.Provider"/>
</context:component-scan>
But the mistery is deeper than I first thought... I am more confident that I am on the right track and just missed a step!
A much better approach is to use JSR-330 annotations.
Instead of #Autowired, prefer using #Inject. Spring supports JSR-330 annotations and will use Autowire implementation under the covers. For your Spring beans annotated with #Component, #Service, simply replace the annotation with JSR-330 specific #Named.
If you're using maven, simply include the following in your pom.xml file.
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
Using JSR-250's #Resource instead of #Autowired is a big step forward; it does what is needed from #Autowired and it is JSR and not Spring specific.
Could be good enough for many uses.

I want catch all Exception logs for AOP with best performance

I heaard that spring AOP is slower 30 times than aspectj.
So, I insert below code in the spring context xml.
<aop:aspectj-autoproxy />
so, is aspectj applied to?
plz let me know and any idea that can substitute aop for better performance!!
<aop:aspectj-autoproxy/>
Just enables #AspectJ annotation support .The AOP runtime is still pure Spring AOP . See the following from spring reference.
#AspectJ refers to a style of declaring aspects as regular Java classes annotated with
Java 5 annotations. The #AspectJ style was introduced by the AspectJ project as part of
the AspectJ 5 release. Spring 2.0 interprets the same annotations as AspectJ 5, using a
library supplied by AspectJ for pointcut parsing and matching. The AOP runtime is still
pure Spring AOP though, and there is no dependency on the AspectJ compiler or weaver.
If you want to use Aspectj compiler/weaver , check here .

Resources