contex:componet-scan not picking up beans defined in jar file - spring

I am working on a Spring Project:Common that uses a combination of Annotaions and Spring IOC in XML.
I have a common.jar which contains Common classes used by various projects.
And I have another Spring Project:WebService that refers to the beans defined in common.jar.
For some reason beans marked with #Component Annotation in Common.jar are not being picked up by my WebService Project. But all beans defined using <bean id="" class="" /> in Common.jar were picked up.
Below are the code for all files that have necessary configuration. Would really appreciate your help. Thanks in advance.
In Common.jar, applicationContext.xml
<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:aop="http://www.springframework.org/schema/aop"
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://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<import resource="springConfig/app/AppServices.xml"/> <!-- Beans in this file were loaded. -->
<context:annotation-config/>
<context:component-scan base-package="com.ipd.app1"/> <!-- Beans for all classes under app1 package were NOT loaded -->
</beans>
In Common.jar, AppServices.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="inquireOrderApp" class="com.ipd.app.inquireOrderDetail.InquireOrderDetailAppImpl"/>
</beans>
Common.jar, com.test.app.MyClass
package com.ipd.app1;
#Component("createOrderApp")
public class CreateOrderAppImpl implements CreateOrderApp {
#Override
public CreateOrderResponse processMSSOrder(TransactionContext tx,
CreateOrderRequest createOrderRequest)
throws ApplicationException, Exception {
System.out.println("In App Layer Class CreateOrderAppImpl to ProcessOrder.");
return response;
}
}
WebService Project, IpdService_IPDSoapHTTPPortImpl.java
#WebService(portName = "IpdSoapHTTPPort", serviceName = "IpdService", targetNamespace = "http://ipd.com/ipdIpdweb/", wsdlLocation = "/wsdls/Ipd.wsdl", endpointInterface = "com.ipd.ipdIpdweb.IpdPortType")
#BindingType("http://schemas.xmlsoap.org/wsdl/soap/http")
public class IpdService_IpdSoapHTTPPortImpl implements IpdPortType {
ApplicationContext ctx;
public IpdService_IpdSoapHTTPPortImpl() {
this.ctx = AppContext.getCtx();
}
#Override
public void createOrder(WSHeader wsHeader,
CreateOrderRequest createOrderRequest,
Holder<WSResponseHeader> wsResponseHeader,
Holder<CreateOrderResponse> createOrderResponse)
throws WSException {
CreateOrderApp createOrderApp = (CreateOrderApp) ctx.getBean("createOrderApp");
res = createOrderApp.processOrder(tx, createOrderRequest);
res.setResponseCode(BigInteger.valueOf(0));
res.setResponseMessage("Success");
.....
}
}
Please let me know if you need see the code for any other file.

Well add this to applicationContext.xml
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>

Related

Spring Java Unit Testing; How do i initialise a beans property at the point of #BeforeClass?

In a test class I have a static
.
.
.
#BeforeClass
public static void setUpBeforeClass() throws Exception {
//Set utility beans property
// Not a System property.
}
At this point, How do i initialize or set the property of a bean ?
Thanks
If you want to setup in setUpBeforeClass() method, this is impossible. But if you just want to setup it and you're using xml configuration this is an other way.
Generally speaking, you need to create an applicationContext.test.xml which overide the applicationContext.xml. Use it in JUnit instead of applicationContext.xml
For e.g. here is your applicationContext.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"
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">
<context:annotation-config />
<bean name="utilBean" class="UtilBean">
<property name="prop1" value="1"/>
</bean>
<bean name="anotherBean" class="AnotherBean">
<property name="propAnother" value="10"/>
</bean>
</beans>
For setting the 'prop1' with 2 in 'utilBean', you should create a new applicationContext.test.xml like this:
<?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"
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">
<!-- import the original one -->
<import resource="classpath*:applicationContext.xml" />
<!-- Override utilBean -->
<bean name="utilBean" class="UtilBean">
<!-- Override prop1 value -->
<property name="prop1" value="2"/>
</bean>
</beans>
Then in your JUnit class, use applicationContext.test.xml instead of applicationContext.xml
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath*:applicationContext.test.xml" })
public class JunitTest {
// your tests
}
Your prop1 value of utilBean is set with '2' in your JunitTest, but in your original process it will always be '1'
You can also use antoherBean in your JUnit, it's 'propAnother' value equals to 10, both in JUnit and in original process.
Sorry I didn't saw comments... In your case, override the configuration in this way:
#Import(ApplicationContext.class)
#Configuration
public class TestApplicationContext {
...
}
Then override your bean. Use this configuration class instead of the original one in your JUnitClass
In your test class declaration:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class MyTest {
//... your tests
#Configuration
public static class Config {
//your configuration for the test
}
} // end of test class

Spring AOP Pointcut not called

i work with JSF 2.2 + Spring framework 3.2.4
So, i have this applicationContent.xml
<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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<aop:aspectj-autoproxy proxy-target-class="true" />
<tx:annotation-driven transaction-manager="transactionManager"/>
<context:annotation-config/>
<context:component-scan base-package="com.vulcan.controller" />
<context:component-scan base-package="com.vulcan.service" />
<context:component-scan base-package="com.vulcan.dao" />
<context:component-scan base-package="com.vulcan.spring.aop" />
.....
Then i have aspect component
in
package com.vulcan.spring.aop;
#Aspect
public class LoggingService {
private Log log = LogFactory.getLog(this.getClass());
#Pointcut("execution(* *.*(..))")
protected void loggingOperation() {}
#Before("loggingOperation()")
public void logJoinPoint()
{
System.out.println ("Hello");
}
....
With this type of execution i assume this pointcut will be triggered on every methods. But the problem is, this pointcut isn't triggered ? Any idea why ? Thanks
FYI, i using glassfish 4, and when i deploy my web app i didn't receive any error configuration. So i assume my configuration is fine.
#Aspect annotate classes aren't automatically detected by Spring and because it isn't detected it isn't known to the <aop:aspectj-autoproxy /> beans. So basically there is no aspect.
Either add #Component to your #Aspect annotated class(es) so that Spring can detect and use the aspect.
#Compopnent
#Aspect
public class LoggingService { ... }
or declare the aspect explictly in your xml file
<bean class="LoggingService" />
Either way the aspect will be picked up by the <aop:aspectj-autoproxy /> beans and the advice will be run.
Try using execution(* *(..)).

Inject property to spring bean using annotation

As explained here and here it is quite clear how to do it but still can't seem to make it work.
I simply like to use the #Value annotation in order to inject a property to a spring bean. I created a basic spring MVC project with one controller and one bean.
Here is my application context:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util" xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd
http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.1.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<context:component-scan base-package="me.co.fatsecret" />
<!-- Properties -->
<bean id="props"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:fatProperties.properties" />
</bean>
</beans>
I have one bean called Configuration:
package me.co.fatsecret;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
#Component
public class Configuration {
/*--- Members ---*/
#Value("${api_key}")
protected String API_KEY;
#Value("${api_secret}")
protected String API_SECRET;
#Value("${api_url}")
protected String API_URL;
/*--- Constructors ---*/
public Configuration() {
}
/*--- Getters & Setters ---*/
public String getAPI_KEY() {
return API_KEY;
}
public void setAPI_KEY(String aPI_KEY) {
API_KEY = aPI_KEY;
}
public String getAPI_SECRET() {
return API_SECRET;
}
public void setAPI_SECRET(String aPI_SECRET) {
API_SECRET = aPI_SECRET;
}
public String getAPI_URL() {
return API_URL;
}
public void setAPI_URL(String aPI_URL) {
API_URL = aPI_URL;
}
}
Now I have only one controller, injected with this Configuration class and as I call this controller I see that the values in the Configuration class are not populated right.
My properties file is located under the resources folder (src/main/resources) and is a part of my classpath (done by default since this is a maven project). Here it is:
api_url=http://platform.fatsecret.com/js?
api_key=SomeKey
api_secret=SomeSecret
The file name is fatProperties.properties.
As I debug my server when calling the controller I see that the content of the Configuration class is:
${api_key}
${api_secret}
${api_url}
This is the actual value of the Strings, wich means that the vales from the properties file are not getting injected for some reason.
Am I missing something here?
UPDATE1: I replaced the PropertyPlaceholderConfigurer bean with:
<context:property-placeholder location="classpath:fatProperties.properties"/>
Getting the same result
Ok, got it!
I'm using a spring MVC project, which means I have a separated context for my web layer (the controllers). The "Configuration" bean which hods the properties using the #Value annotation is injected to a controller. My property-placeholder is defined within my root-context hence it cannot be seen from my controller. To resolve the issue I simply added the property-placeholder definition to my DispatcherServlet context and it works like a charm :)
Add this to your application context file:
<context:property-placeholder location="classpath:fatProperties.properties" />
Try
#Value("#{props['api_key']}")
private String apiKey;

Spring bean not injected into CXF web service, Why?

I am writing a RESTful service (using CXF on JBoss) in which I have inject another class using Spring (Autowired). But the class is not getting injected and is null.
Web Service Interface and Class (Where injection needs to happen)
package com.company.project.web;
#Path("/myws")
public interface IMyWebService {
#POST
#Path("/doSomething")
#Consumes("application/json")
#Produces("application/json")
MyResponse doSomething(MyRequest myRequest)
}
#Service("myWebService")
public class MyWebService implements IMyWebService {
#Autowired
private IMyCore myCore;
public MyResponse doSomething(MyRequest myRequest) {
....
}
}
That which has to be injected
package com.company.project.biz;
public interface IMyCore {
MyResponse doSomething(MyRequest myRequest);
}
#Component("myCore")
public class MyCore implements IMyCore {
public MyResponse doSomething(MyRequest myRequest) {
.....
}
}
Beans.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:jaxws="http://cxf.apache.org/jaxws"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-http.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<context:annotation-config />
<context:component-scan base-package="com.company.project"/>
<jaxrs:server id="myWebService" address="/">
<jaxrs:serviceBeans>
<bean class="com.company.project.web.MyWebService" />
</jaxrs:serviceBeans>
<jaxrs:extensionMappings>
<entry key="json" value="application/json" />
</jaxrs:extensionMappings>
</jaxrs:server>
</beans>
My service is active (http://localhost:8080/{warname}/myws/doSomething) but the MyCore instance is not being injected into MyWebService (in the myCore field). It is always null and my service does not work as expected, instead throws NullPointerException
Tried all inputs gathered over google. No luck! Your help is highly appreciated.
Regards
Try to add below method to your web service:
#PostConstruct
public void init() {
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
The current web application context (usually the one loaded by ContextLoaderListener) will be used for autowiring, so the IMyCore bean has to be defined in the context listener configuration file and not in the web service one.
If you want to use Spring Beans in CXF Web Service class, then declare WebService as following in the XML configuration file of the CXF (e.g. spring-cxf.xml)
<bean id="hello" class="demo.spring.service.HelloWorldImpl" />
<jaxws:endpoint id="helloWorld" implementor="#hello" address="/HelloWorld" />
Declare separated bean for the WebService class and then put it in the endpoint with an ID. Like this you will have spring managed bean, where you can use AutoWired annotations as well.
Your beans never won't be injected automatically if you will declare your web service as following.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
<jaxws:endpoint id="helloWorld" implementor="demo.spring.service.HelloWorldImpl" address="/HelloWorld"/>
In this case you will need either:
Inject spring beans manually
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
Or retrieve the beans one by one from the spring context
ApplicationContext context = ...; // your Spring ApplicationContext
HelloBean helloBean = (HelloBean) context.getBean("bean");
I haven't tried this for JAX-RS, but the approach in my opinion should be the same.
From CXF official documentation.
Try to add below bean configuration at Beans.xml
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>
In my case, it worked..

Adding Xml configurations to a Spring ApplicationContext that is already setup

I was wondering if there is a way to do the following:
have my wep app startup with its servle-context.xml
When, at a certain point, one particular bean in this xml config is instantiated, it will add it's own xml configuration to the application context (or to a child perhaps?).
I'm asking this because I want to pack some functionality in a stand alone library and then reuse it in different projects, so that initializing a bean of this library will load its xml config.
What I wrote is:
public class IrisLibHelper {
ApplicationContext context;
ApplicationContext irisContext;
#Required
#Autowired
public void setContext(ApplicationContext ctx){
this.context = ctx;
ClassPathXmlApplicationContext xap = new ClassPathXmlApplicationContext(ctx);
xap.setConfigLocation("classpath:com/dariodario/irislib/xmldefs/irisconfig.xml");
this.irisContext = xap;
}
public ApplicationContext getIrisContext() {
return irisContext;
}
public void setIrisContext(ApplicationContext irisContext) {
this.irisContext = irisContext;
}
}
and the irisconfig.xml is:
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<!-- <context:component-scan base-package="com.dariodario"></context:component-scan> -->
<mvc:annotation-driven />
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"
p:synchronizeOnSession="true" />
<context:component-scan base-package="com.dariodario.iris.controllers"></context:component-scan>
</beans>
The problem is that it doesn't seem to scan the com.dariodario.iris.controllers package, in fact the controllers don't get mapped! (I've logging debugging on and I don't seen anything).
Why not use the tag <import resource="classpath:applicationConfig.xml" /> ? You can load a spring configuration file which is in jar. In a jar, the Spring XML configuration is always at the root. But if not, you can use this notation: <import resource="${configurablePath}/applicationConfig.xml" /> where configurablePath can be reach by a property place holder or other.
I think this way is cleaner than merging two Spring context.

Resources