CDI doen't work in a simple Websphere Liberty Profile setup - websphere-liberty

I have Websphere Liberty Profile (wlp-beta-javaee7-2015.4.0.0.zip) installed on a local computer with the following server.xml file on server:
<?xml version="1.0" encoding="UTF-8"?>
<server description="new server">
<!-- Enable features -->
<featureManager>
<feature>jsp-2.3</feature>
<feature>cdi-1.2</feature>
<feature>ejbLite-3.2</feature>
<feature>jaxrs-2.0</feature>
<feature>jpa-2.1</feature>
<feature>jaxrs-2.0</feature>
<feature>jaxrsClient-2.0</feature>
<feature>concurrent-1.0</feature>
<feature>jndi-1.0</feature>
<feature>localConnector-1.0</feature>
</featureManager>
<httpEndpoint id="defaultHttpEndpoint" httpPort="9080" httpsPort="9443" />
<applicationMonitor updateTrigger="mbean" />
<application id="test2_ear_exploded" location="C:\myfolder\test2\out\artifacts\test2_ear_exploded" name="test2_ear_exploded" type="ear" />
</server>
The application is a trivial JSP page that calls a bean method. That method uses an #Inject-ed bean:
package pkg1;
import javax.inject.Inject;
public class Test {
#Inject
private Bean1 bean1;
public String test() {
return bean1.testMethod();
}
}
After application startup I get NullPointerException there. It seems to me that CDI injection is not working.
Can anybody help me with that?

The error suggests Test is not a bean. If you want to perform injection on a class, the class should be either a Bean or JavaEE components detailed in Table EE.5-1 of EE7 specification.
Test class has no bean defining annotation, so it is not a bean in an implicit bean archive (no beans.xml or having a bean.xml but bean-discovery-mode="annotated").
To fix the problem, you can either annotate Test.java with a Bean Defining annotation such as Dependent, ApplicationScoped etc. Alternatively, add a blank beans.xml or beans.xml with bean-discovery-mode="all", which effectively makes Test as a bean with Dependent scoped.

I used #Inject in the JSP code which appears to be not working in JSPs.
When I moved all injection to Java and used CDI BeanManager to instantiate the first bean, all the other #Injects started to work.
Not very convenient, but proved CDI is working.

Related

Why we use factory-method="aspectOf" in aspect configuration

I found some code in my project.By seeing that i am confused how it scanning the package.we are not mentioning aspect package com.abc.b any where.I have few question
Why aop:aspectj-autoproxy is commentout in xml file?
why is used ?
How com.abc.b package is scanned by spring or there is no need of it or It has link from 'factory-method="aspectOf"'
serviceContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd" default-lazy-init="true">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<!-- <aop:aspectj-autoproxy /> -->
<!-- Enable message logging using the CXF logging feature -->
<cxf:bus>
<!-- <cxf:features>
<cxf:logging/>
</cxf:features> -->
<cxf:inFaultInterceptors>
<bean class="com.flipswap.interceptor.cxf.SafeLoggingInFaultInterceptor"/>
</cxf:inFaultInterceptors>
</cxf:bus>
<context:component-scan base-package="com.abc.service.impl,">
<context:exclude-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/>
</context:component-scan>
<bean id="eSSyncAspect" class="com.abc.b.ES" factory-method="aspectOf"/>
.
.
.
ES.java
package com.abc.b;
#Aspect
public class ES{
// some code
}
Unless you specify a custom instantiation model, aspects are by default singletons. That means - in case your code is properly woven -, that you can access the singleton instance of the aspect with AspectName.aspectOf().
In order for your classes to be woven by the AspectJ weaver, you need to either use compile-time/build-time weaving or load-time weaving.
In your spring configuration you are telling Spring to configure your aspect as a spring bean by telling how to access the singleton instance (through the static 'factory' method aspectOf). Spring will do the usual configuration (autowiring and any configured post-processors) on the singleton aspect instance.
aop:aspectj-autoproxy is commented out in your configuration because that would conflict with native aspectj support, as it would enable Spring AOP's dynamic proxy based AOP solution, which is very limited compared to native aspectj, and has a different mechanism to configure aspect beans than the one used in your configuration, namely through the static factory method AspectName.aspectOf().
In most cases, AspectJ aspects are singletons, with one instance per class loader. This single instance is responsible for advising multiple object instances.
A Spring IoC container cannot instantiate an aspect, as aspects don't have callable constructors. But it can obtain a reference to an aspect using the static aspectOf() method that AspectJ defines for all aspects, and it can inject dependencies into that aspect.
7.2.1.1. Example
Consider a security aspect, which depends on a security manager. This aspects applies to all changes in the value of the balance instance variable in the Account class. (We couldn't do this in the same way using Spring AOP.)
The AspectJ code for the aspect (one of the Spring/AspectJ samples), is shown below. Note that the dependency on the SecurityManager interface is expressed in a JavaBean property:
public aspect BalanceChangeSecurityAspect {
private SecurityManager securityManager;
public void setSecurityManager(SecurityManager securityManager) {
this.securityManager = securityManager;
}
private pointcut balanceChanged() :
set(int Account.balance);
before() : balanceChanged() {
this.securityManager.checkAuthorizedToModify();
}
We configure this aspect in the same way as an ordinary class. Note that the way in which we set the property reference is identical. Note that we must use the factory-method attribute to specify that we want the aspect "created" using the aspectOf() static method. In fact, this is locating, rather than, creating, the aspect, but the Spring container doesn't care:
<bean id="securityAspect"
class="org.springframework.samples.aspectj.bank.BalanceChangeSecurityAspect"
factory-method="aspectOf">
<property name="securityManager" ref="securityManager"/>
</bean>We don't need to do anything in Spring configuration to target this aspect. It contains the pointcut information in AspectJ code that controls where it applies. Thus it can apply even to objects not managed by the Spring IoC container.

Prevent Spring from meddling with CDI annotations even for factory created instances

I have a legacy product's JAR that contain Spring (4.3.8) managed classes. I need to integrate it with CDI (JavaEE 7).
I have an interface from the legacy JAR, that is implemented by a CDI bean. The CDI bean is requested from the CDI BeanManager and returned from a factory method. The factory method is registered inside Spring XML and works as expected.
The problem occurs, when a Spring bean of the legacy JAR depends on the implemented interface. Spring than injects the CDI implementation instance and scans the class it for known annotations, namingly #Inject. It then tries to resolve the dependency, which doesn't work since the dependency is not available to Spring.
I already tweaked context:property-placeholder excludes, but that changes nothing.
So how can I tell Spring to stop trying to inject something in my factory produced bean instance?
I finally was able to solve (work around) the problem. I had to remove all CDI-Annotations in the legacy JAR (by replacining them with their Spring counterparts), so spring would any longer work.
Then I added the following XML block to the applicationContext.xml of my CDI WAR:
<context:component-scan annotation-config="false" base-package="com.example">
</context:component-scan>
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor">
<property name="autowiredAnnotationTypes">
<set>
<value>org.springframework.beans.factory.annotation.Autowired</value>
<value>org.springframework.beans.factory.annotation.Value</value>
</set>
</property>
</bean>
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
<bean class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
<property name="customQualifierTypes">
<set>
<value>org.springframework.beans.factory.annotation.Qualifier</value>
</set>
</property>
</bean>
Basically that drops the support for #Inject, etc. from Spring and leaves it where it belongs: CDI.
It's a bit easier.
AutowiredAnnotationBeanPostProcessor is already a bean, so you can configure it before Spring starts to scan with a ServletContextListener to exclude #Inject annotations. At least from Spring 4.1+, AutowiredAnnotationBeanPostProcessor has a method setAutowiredAnnotationTypes, e.g.:
#WebListener
public class ApplicationConfigListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent event) {
ApplicationContext appCtx = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<Class<? extends Annotation>>();
AutowiredAnnotationBeanPostProcessor bean = appCtx.getBean(AutowiredAnnotationBeanPostProcessor.class);
autowiredAnnotationTypes.add(Autowired.class);
autowiredAnnotationTypes.add(Value.class);
bean.setAutowiredAnnotationTypes(autowiredAnnotationTypes);
}
}
You could use a SpringBeanAutowiringInterceptor too.
This is explained here.

Spring Lazy-init not working with #Resource injection

I have an interface with real and mock implementation. for obvious reasons the mock implementation is not in the production classpath.
I inject the bean using:
#Resource (name="${myClient}")
I am using Spring MVC and injecting this into a #Controller.
In external configuration I set the actual bean name to use and bind it to 'myClient' parameter. The binding works and it tries to load the real implementation but also fails on ClassNotFound on my mock although marked as lazy-init=true.
I am using Spring 4.0.0.
I know this is expected when suing #Autowire, but with #Resource I don't expect it to try and instantiate all beans in spring xml.
Any ideas wha't going on?
Here is the stack trace:
Caused by: org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [MyMock] for bean with name 'myClientMock' defined in URL [file:/C:/myProject/target/classes/META-INF/springContext.xml]; nested exception is java.lang.ClassNotFoundException: MyMock1
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1327)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:594)
at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1396)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:382)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:361)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:347)
at org.springframework.context.support.AbstractApplicationContext.getBeanNamesForType(AbstractApplicationContext.java:1051)
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.initHandlerMethods(AbstractHandlerMethodMapping.java:105)
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.afterPropertiesSet(AbstractHandlerMethodMapping.java:89)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.afterPropertiesSet(RequestMappingHandlerMapping.java:163)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549)
I dont know if you´re using Spring profiles, but it´s what we use here to initialize different beans per environment.
From Tomcat we spcecify which profile use, and in Spring we have configure something like this.
<beans profile="deployed-local">
<util:properties id="propertyConfigurer" location="classpath:app.deployed-performance.properties"/>
<context:property-placeholder location="classpath:app.deployed-performance.properties,classpath:app.constants.properties"/>
<import resource="spring/jdbc-config-test.xml"/>
<import resource="spring/contacts-config-deployed.xml"/>
<import resource="spring/security-config-local.xml"/>
<import resource="spring/clamAV-service.xml"/>
<import resource="spring/document-service.xml"/>
</beans>
<beans profile="deployed-prod">
<import resource="spring/jdbc-config.xml"/>
<import resource="spring/contacts-config-deployed.xml"/>
<import resource="spring/security-config.xml"/>
<import resource="spring/clamAV-service.xml"/>
<import resource="spring/document-service.xml"/>
</beans>

Making Spring aware of Jersey filter

I have a class which implements ContainerRequestFilter, i want to inject some spring dependencies into it so i need to make Spring aware of the Jersey filter. The filter itself is configured in my web.xml with the Jersey servlet
<servlet>
<servlet-name>Jersey Spring Web Application</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
<param-value>com.MyFilter</param-value>
</init-param>
</servlet>
The filter class then attempts to inject the Manager bean. In order to make spring aware of the Filter bean i have defined the bean in my applicationContext.xml and included.
#Component
public class MyFilter implements ContainerRequestFilter {
#Autowired
private Manager manager;
I've attempted to make the filter bean visible by forcing Spring to use proxy generated classes however this is not working
<mvc:annotation-driven />
<aop:aspect-autoproxy />
<bean id="filter" class="com.MyFilter">
<property name="manager" ref="Manager" />
</bean>
Any suggestions on how i can edit existing code to allow the filter see spring beans?
Since you are using Jersey's Spring Servlet, spring dependencies can be injected into the filter using the annotation #InjectParam
//#Component -> This is not required.
public class MyFilter implements ContainerRequestFilter {
#InjectParam
private Manager manager;
I feel this is the idiomatic way of using Jersey and Spring together.
This is something that is quite common for Spring Security applications. You should utilize the DelegatingFilterProxy for this.
You will add this filter to your web.xml via the <filter> tag, and you then configure it as a bean in your application container. You can then use it to delegate to a Spring configured filter that you have in your application context.
I am unfamiliar with how Jersey's SpringServlet work, but that is how I would delegate to a Spring configured filter.

Inject external object in a spring bean

I have a noob spring question.
if i have a bean that is dependent on google's gdata api jars. How I represent this in a beans.xml file?
<bean class="com.google.foo.bar.ExternalClass" id="yourExternalBeanName" />
Then you can inject this 3rd party bean in your classes. With XML:
<property name="yourProperty" ref="yourExternalBeanName" />
or annotations:
#Inject
private ExternalClass yourProperty;

Resources