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
Related
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.
I'm trying to set up a local overrides file for some of my bean definitions. Yes, it's a fragile system, but it's just for testing. Basically, I've got one XML file which looks more or less like:
<?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:util="http://www.springframework.org/schema/util"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
<!-- so many beaaaannzzz -->
<utils:list id="partnerList" value-type="my.partner.Class">
<ref bean="previouslyDefinedBean"/>
</utils:list>
<!-- include local bean definition overrides -->
<import resource="file://${user.home}/somedirectory/prefix-*.xml"/>
</beans>
This works in general, but it has an unexpected and undesirable result with the utils:list element.
My somedirectory/prefix-*.xml override file defines another list:
<utils:list id="partnerList" value-type="my.partner.class">
<ref bean="otherBean"/>
</utils:list>
When it is picked up however, I get an undesired result: partnerList has two beans in it, previouslyDefinedBean and otherBean, while I want it to only have the latter.
Now, I'm aware Spring offers some weird weird collection merging, so I tried setting <utils:list merge="false"... but that blew up as an unsupported attribute. Is there something I can do to continue using this override system for the util:list, or have I got to take another tack entirely?
Hoping you may be able to help. My Spring knowledge is extremely limited to apologies if the solution is something really obvious.
Here are the contents of the relevant files:
application-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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="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/util
http://www.springframework.org/schema/util/spring-util-3.1.xsd">
<context:annotation-config />
<util:properties id="messageConfig" location="classpath:customMessages.properties"/>
</beans>
/src/main/resources/customMessages.properties:
sms.message=Test
Java class:
#Controller
public class ApiRestController implements ApiRest {
#Value("#{messageConfig['sms.message']}")
private String smsMessage;
public final void setSmsMessage (String smsMessage)
{
this.smsMessage = smsMessage;
}
...
}
However, when referencing the 'smsMessage' variable elsewhere in the Java class, the value is NULL. Any ideas what I might be missing? Any pointers would be really appreciated.
Add
<context:component-scan base-package="spring-controllers-package"/>
to the application-context.xml
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.
i want to define an #Around aspect for a method of my #Entity
All my entities are in package data.entity
A define an aspect like this:
#Aspect
public class TestAspect {
#Around("execution(* data.entity..*(..))")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("INTERCEPT: "+pjp.toLongString());
return pjp.proceed();
}
}
But never is intercepted... where is my error?
In spring xml i have 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:tx="http://www.springframework.org/schema/tx"
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-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/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<context:component-scan base-package="data.dao, data.service" />
<tx:annotation-driven proxy-target-class="true"/>
<aop:aspectj-autoproxy/>
<bean id="testAspect" class="spring.TestAspect" />
... datasource and other ...
</beans>
I try also
#Around("target(data.entity.MyEntity)")
and
#Around("target(data.entity..)")
but still not work.
Thanks.
It looks like you use spring-proxy-aop. This works only if the class is a spring manged bean, and the adviced method must be invoked from an other object.
Try to use real aspectJ instead of spring-proxy-aop.
I have just started using AOP and below are the findings at my level
i am assuming you have necessary jar files, aspectjweaver-1.6.10.jar and org.springframework.aop-3.0.5.RELEASE.jar present in your apps classpath.
The method aroundAdvice, as you have defined currently is perfect.
Could you remove the below line and try.
<context:component-scan base-package="data.dao, data.service" />