I'm trying to inject a bean that was defined on a XML into an annotated, It is only annotated and not declared on XML, I think that is just something that I'm missing here is my *context.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:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-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/jee
http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
...
<bean id="userBusiness" class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">
<property name="jndiName" value="java:global/app-common/app-common-core/UserBusinessImpl" />
<property name="businessInterface" value="com.app.common.business.UserBusiness" />
</bean>
...
<context:annotation-config/>
<context:component-scan base-package="com.app.common.jsf" />
</beans>
Here's the component:
#Component
public class AppAuthorization {
#Autowired
private UserBusiness userBusiness;
#Autowired
private AppLogin sabiusLogin;
...
#Local
public interface UserBusiness {
User listUserByFilter(User user) throws UserBusinessException;
...
#Stateless
#Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
#Interceptors({SpringBeanAutowiringInterceptor.class})
public class UserBusinessImpl implements UserBusiness {
#Autowired
private ProgramasUsuariosDao programasUsuariosDao;
...
When I try to access the AppAuthorization Spring says that:
Could not autowire field: private com.app.common.business.UserBusiness com.app.common.jsf.AppAuthorization.userBusiness"
Seems that the annotated bean can't see the declared one, but search and seems that I only needed to add the annotation-config to the XML, is this right? Hope some can help me.
EDIT
I think that this is the most important part of the stack trace:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.app.common.business.UserBusiness] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:997)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:867)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:779)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:503)
... 201 more
Following the steps on the context creation I see no bean registered tha can be seen by annotations just when springs creates the context based on the xml is that I can see all the beans that wre created.
EDIT 2
This is the beanRefContext.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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="contexts" class="com.app.common.spring.ClassPathXmlApplicationContext" />
</beans>
This is the class that loads the XML context files:
public class ClassPathXmlApplicationContext extends org.springframework.context.support.ClassPathXmlApplicationContext {
public ClassPathXmlApplicationContext() {
super((System.getProperty("module.context.file").split(";")));
}
}
As I said, the annotated beans cannot see the XML ones so, spring cannot autowire them.
EDIT 3
I don't have a #Configuration bean (I'm not using AnnotationConfigApplicationContext), all the config is in the XML and if I try to create one the server doesn't start, it's a legacy system with spring 3.2 and EJB 3.0 and I can't change this aspect now.
Thanks in advance!
I think you missed to specify #Component annotation for the UserBusiness class
EDIT:
Can you make the component-scan config to com.app.common instead of com.app.common.jsf
What seems to work was create a #Configuration import the xml that have the bean declaration (with #ImportResource) and don't scan it's package in XML.
For some reason if I declare the file in the XML the server don't start, it's strange because I have no definition anywhere that I'm using an annotation configuration.
Related
I've read Spring In Action, and prefer Java config over XML config. So I used Java config to write my app, but our deployment environment requires me to use XML config. So I wrote an XML config, and it's only function is to import the root Java config.
The Java config code looks like this:
package com.somegroup.app;
#Configuration
#ComponentScan(basePackages = "com.tianchengsys.crawlers.cqs")
public class AppCtxConfig {
#Bean
public SomeType aSomeType() {
return new SomeType()
}
}
and the XML config looks 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:p="http://www.springframework.org/schema/p"
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:dubbo="http://code.alibabatech.com/schema/dubbo"
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/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<context:annotation-config />
<bean class="com.somegroup.app.AppCtxConfig" lazy-init="false" />
</beans>
When I created a ClasspathXmlContext("classpath:spring-context.xml") in Eclipse, the SomeType bean defined in Java config is initialized, and registered to springs ApplicationContext. But when I deployed this app (all dependencies are in a lib directory), the AppCtxConfig bean defined in the XML config was just treated an ordinary bean (not configuration).
It was created, but the beans defined in it were not initialized. Spring some times warned the someType method in the Java config should be static. I did changed it to static, it also didn't work.
This is because you are creating AppCtxConfig as a regular bean, which it isn't.
As the commentor suggested, add the component-scan on and set base-package to the package where your config class is located in:
<!-- Scan the JavaConfig -->
<context:component-scan base-package="com.somegroup.app" />
If your app package is the root package, with all subpackages inside, add a new config package and move the AppCtxConfig inside it.
So add:
<!-- Scan the config package with AppCtxConfig inside it -->
<context:component-scan base-package="com.somegroup.app.config" />
I'm having trouble trying to create a map in Spring config, since the keys I define are replaced when the map is autowired.
I defined the map in my spring-config.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:util="http://www.springframework.org/schema/util"
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/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="basePackageWhereMyBeansAre"/>
<util:map id="beanMapper" map-class="java.util.HashMap">
<entry key="QueryType1" value-ref="bean1"/>
<entry key="QueryType2" value-ref="bean2"/>
</util:map>
</beans>
I try to autowire the map in my Java code:
#Resource
Map<String, BeanSuperClass> beanMapper;
#Autowired
DefaultBeanClass defaultBean;
public String callMethod(Query query) {
BeanSuperClass bean = beanMapper.getOrDefault(query.getTypeName(), defaultBean);
...
}
The problem is that when I debug the Java code and I check the beanMapper object, I can see that the keys for the entries are replaced with the bean names:
beanMapper {
entry: key="bean1" (the bean name), value=bean1 (the actual bean)
entry: key="bean2" (the bean name), value=bean2 (the actual bean)
}
so beanMapper.getOrDefault() always returns the defaultBean.
Does anyone knows why the keys are replaced? What am I doing wrong?
Thanks in advance
I'd like to test some services that them themself contain other autowired services. But these "external" services are not required for the test itself.
How can I create a test setup, eg for the following example?
package de.myapp.service;
#Service
public class MyServiceDelegator {
#Autowired
private List<ServiceInterface> services;
public ServiceInterface delegate(String id) {
//routine to find the right ServiceInterface based on the given id
}
}
#Service
public class MyService implements ServiceInterface {
}
#Service
public class MyCustomService implements ServiceInterface {
//that is the problem during testing
#Autowired
private de.myapp.repository.SomeDao dao;
}
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("applicationContext.xml")
public class ServiceDelegatorTest {
#Autowired
private ApplicationContext ac
#Test
public void testDelegator() {
MyServiceDelegator dg = ac.getBean(MyServiceDelegator.class);
ac.delegate("test");
}
}
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="de.myapp.service" />
</beans>
Problem: All services that contain autowired dependencies from packages that are not scanned within the JUnit test (like MyCustomService), will throw an Exception:
Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type [SomeDao] found for dependency: expected at
least 1 bean which qualifies as autowire candidate for this
dependency. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1103)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:963)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
... 57 more
You can use Springockito to add mocked service implementations to your test application context.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mockito="http://www.mockito.org/spring/mockito"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
http://www.mockito.org/spring/mockito
http://www.mockito.org/spring/mockito.xsd">
<context:component-scan base-package="de.myapp.service" />
<mockito:mock id="dao" class="de.myapp.repository.SomeDao" />
</beans>
The problem is that SomeDao is not being picked up by component scanning because it's not under the de.myapp.service package.
You have explicitly stated that the package for component scanning is de.myapp.service.
I sugggest you make the following change:
<context:component-scan base-package="de.myapp" />
That way all the code under de.myapp will be eligible for component scanning.
If you want to avoid including all your code in component scanning you could do the following:
<context:component-scan base-package="de.myapp.service, de.myapp.repository" />
I tried to change the scope of a bean using #Scope annotation. That bean is actually working as MessageSource and used for internationalization purpose.
The schema in mvc-dispacher-servlet.xml is as follows:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
Exception described in console is as follows:
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Cannot locate BeanDefinitionParser for element [scoped-proxy]
Ok. If its a normal bean then most likely you are just missing the xml parser for the scope tag. To be able to use scoped proxies you need to register aop:scoped-proxy.
There is a similar question on SO:
Accessing a session-scoped bean inside a controller
Which results in:
http://static.springsource.org/spring/docs/3.0.x/reference/beans.html#beans-factory-scopes-other-injection
Else you should easily find some tutorials on this topic through google.
It is likely that you have a bean-scoped option outside the bean (I made such mistake and got an error msg like yours) :
<beans>
...
<aop:config proxy-target-class="true"/>
<aop:scoped-proxy proxy-target-class="true"/>
<aop:aspectj-autoproxy proxy-target-class="true"/>
...
Just put that option inside of the bean declaration:
<bean ... target="step">
<aop:scoped-proxy proxy-target-class="true"/>
</bean>
One more thing - I got such error only for scoped beans.
Quick question.
Can you reference Spring classes in the applicationContext.xml, when they are in another jar which you webApp uses?
The JAR (a common jar that contains all my servries and daos etc) is in the WAR file, but when I try to reference a service through the applicationContext.xml, I get the following error:-
Error creating bean with name 'com.myproject.common.test.impl.TestServiceImpl' defined in ServletContext resource [/WEB-INF/context/spring-context.xml]: Instantiation of bean failed; nested exception is java.lang.IllegalStateException: No bean class specified on bean definition
(Note spring-context.xml is imported into the applicationContext.xml without error.)
My context XML:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-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">
<bean id="com.myproject.common.test.impl.TestServiceImpl">
<property name="genericDao" ref="genericDao" />
</bean>
</beans>
My App packages are all under com.myproject.web
My common JARS all under com.myproect.common
Your bean element needs a class attribute:
<bean id="myTestServiceImpl" class="com.myproject.common.test.impl.TestServiceImpl">
<property name="genericDao" ref="genericDao" />
</bean>
The id attribute is just an identifier for the referencing the bean elsewhere in the bean files. The class attribute supplies the name of the class the bean represents.