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-2.5.xsd">
<import resource="classpath:context2.xml"/>
<import resource="classpath:context3.xml" />
Here Context1.xml is getting over written by context2.xml, context 1.xml and context2.xml are both MDB's. context3.xml is not having issues.
COntext 1 and context2 have some same Bean ID's but have different properties and references.
I found the solution . I was using same Bean ID and thought that it was a pre defined bean ID. I did not have much knowledge on spring . So i studied a bit and found out that u can give any bean ID u want for the class which you are referring to.
Related
Hey everyone!
For context I am working on a simple spring project in intelliJ to configure it with HotswapAgent using DCEVM [8u181 build 2 ] along with the compatible JDK [ 8u181 ] on the Payara 5.0 Application Server.
Please bear with me in the next few snippets of code and my plausible explanation of what's happening and this is not a question regarding Spring MVC syntax or it's working.
This is the sample code I am testing on Hotswapping [ Not the Inbuilt on JVM but using DCEVM ] and HotswapAgent[1.3.0]
HelloWorldController.java
#Controller
public class HelloWorldController {
#Autowired HelloService helloService;
#RequestMapping("/hello")
public String hello(
#RequestParam(value = "name", required = false, defaultValue = "World") String name,
Model model) {
model.addAttribute("name", name);
System.out.println( helloService.sayHello() );
return "helloworld";
}
I don't want to include the code for helloService as it might bloat this post.
HelloService.sayHello() just churns out the quintessential Hello World in the console
As you can see above that auto-wiring has been turned on and it does the proper function(said above).
After this I comment out the Autowired Annotation and the function call, and this gives me an error which is :
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.annotation.AnnotationFormatError: java.lang.IllegalArgumentException: Wrong type at constant pool index
Focus on :
java.lang.IllegalArgumentException: Wrong type at constant pool index
I debugged the application and found out that the IllegalArgumentException was raised when AnnotationParser was parsing the annotations of the Spring Controller class from the Constant Pool and the members(of one of the annotation which is 'type' of the annotation) was not correct when it was taken from the Constant Pool of the Class.
So from my knowledge the hotdeploying is not being done correct ( even though HotswapAgent says it has reloaded the class on the Payara Server) or there is something wrong with the JVM communication or the JDK, and I say this because when I do the opposite that is comment out autowiring then hot deploy and then run, so then I get a null pointer exception.
Note: just for added information
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
If anyone needs more information or code or logs on this then I'd be more than happy to clarify. Thank you for your time everyone.
The retention policy of the Autowire is #Retention(RetentionPolicy.RUNTIME).
According to the JVM specification , the annotation should be available in binary form. (Reference : https://docs.oracle.com/javase/specs/jls/se8/html/jls-9.html#jls-9.6.4.2)
My assumption is java keeps the reference in the constant pool of all the classes with RUNTIME annotation. When you hotswap it, the class is hot swapped but constant pool is not refrenshed to reflect the class swap.
There is an similar open issue with hotswapagent : https://github.com/HotswapProjects/HotswapAgent/issues/256
Well this was weird to solve but it's not related to JDK version or DCEVM, but to the dispatcher servlet of Spring.
My Dispatcher Servlet was missing:
<annotation-driven />
Which is why it couldn't register the controller class and caused unwanted behavior. Also missing was the added XML Schemas.
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
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"
Just for completion purposes or if would be of help to anyone, I'll post the complete dispatcher servlet configuration.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
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">
<annotation-driven />
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.test" />
</beans:beans>
Consider the following code:
<amq:transportConnectors>
<amq:transportConnector uri="${esb.endpoint}"/>
</amq:transportConnectors>
It is not able to resolve the uri value. The error I am getting is :
STACKTRACE:
at com.mincom.util.gadget.Starter.run(Starter.java:40)
THROWABLE: org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean
definition with name 'org.apache.activemq.xbean.XBeanBrokerService#0' defined in class
path resource [minestar/esbadapter/service/EsbEmbeddedApacheContext.xml]: Could not
resolve placeholder 'esb.endpoint' in string value "${esb.endpoint}"; nested exception
is java.lang.IllegalArgumentException: Could not resolve placeholder 'esb.endpoint' in
string value "${esb.endpoint}"
Am I doing anything wrong here?
It is quite evident that spring is unable to find the properties file
easiest way is to see the configuration of properties file
my way is to do it like this:
<context:property-placeholder location="required.properties" />
for this you will need to add following in your spring namespace
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
hope it helps,
Good luck!
I have the following scenario:
Spring project A with multiple bean configurations, including a bean named "searchHelper":
<bean name="searchHelper" class="com.test.SearchHelperImpl"/>
where SearchHelperImpl implements "SearchHelper" interface
Spring project B depends on A with a custom SearchHelperBImpl
What I was thinking of making is just copying the whole configuration into the new project and changing what needs to be changed, but that's not convenient and there must be an easier way of doing this.
My question is, how do I override the definition of the "searchHelper" bean to use SearchHelperBImpl instead of SearchHelperImpl? I want to use the same bean name in order for everything that uses this name to use the new implementation. I am using Spring 3.2.2
Thanks
You should be able to utilize the primary xml attribute on your bean element.
<bean name="searchHelper" primary="true" class="com.test.SearchHelperBImpl"/>
Alternatively, if you are using JavaConfig, you can utilize the #Primary annotation.
#Primary
#Bean
public SearchHelper searchHelper() {
return new SearchHelperBImpl();
}
One interesting "feature" (some consider it a bug) of Spring is that a bean with the same name declared later in configuration will override a bean declared earlier in configuration. So if your project B depends on A, and the configuration in A is included in B, and B defines a bean by the same name after the A configuration then the B instance will "win" and that's the instance you will get.
I would not recommend depending on this behavior, but would go with the answer regarding the Primary annotation. I just thought I would bring this up so you would be aware that even without the primary, or in case the one in project A is also primary you would know that the latest definition wins.
NOTE
This answer relates to how to avoid duplicate bean definitions. For overriding see the answer by nicholas.hauschild.
More effective solution to avoid copying is to place all the beans that are common for both projects in a separate XML configuration file, say "common-beans.xml". And in the configuration XML file for the project B (and any other project that needs those beans) you import that file like this:
<import resource="common-beans.xml" />
Simple example
example-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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"
<!--
Assuming common-beans.xml is a Spring config file
that contains the definitions you need to use
in the current project.
-->
<import resource="common-beans.xml" />
<!-- Defining a bean with the implementaion you need -->
<bean name="searchHelper" class="com.test.SearchHelperBImpl"/>
<!-- Some other configurations if needed -->
</beans>
Useful reading:
Composing XML-based configuration
metadata
Spring2.5 had a feature called dependency-check which can be given for a bean tag and default-dependency-check which can be given at the parent level <beans> tag.
Eg: <bean id="soandSo" class="..." dependecy-check=""/>
<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-2.5.xsd"
default-dependency-check="all">
however in Spring3.x these attributes are deprecated, is there any alternate way of setting dependency-check apart from using #Required attribute and any equivalent to default-dependency-check in Spring3.x??
This feature is no loger supported since Spring 3.x. You can achieve similar result by telling Spring to respect #Required and #Autowired annotations. It can be done using any of the following configuration options within XML context file:
<context:annotation-config/>
<context:component-scan base-package="*"/>
You can skip those options by registering appropriate BeanPostProcessors such as AutowiredAnnotationBeanPostProcessor and RequiredAnnotationBeanPostProcessor.
I think no, because In Spring 2.5 annotations were fully embraced and as the framework evolves through these types of changes, its evident that annotations will continue to be a strong driver in keeping the framework as clear and straightforward as possible.
Spring team now encourages developers to use the following alternatives going forward (with Spring 3 and beyond).
Use constructors (constructor injection instead of setter injection)
exclusively to ensure the right properties are set. Create setters
with a dedicated init method implemented.
Create setters with #Required annotation when the property is required.
Use #Autowired-driven injection which also implies a required property by
default.
Let's say I have following Spring config (version of Spring is 3.0.3):
<?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="theFactoryBean" class="wax.MyFactoryBean"/>
<bean id="factoryBeanUser" class="wax.FactoryBeanUser">
<!-- what should be placed here?-->
</bean>
</beans>
I have instance of FactoryBean implementation and some other instance. I need Spring to inject to other instance FactoryBean, not the object it produces.
There are two possible ways to solve it.
First one, obvious and malfunctional:
<bean id="factoryBeanUser" class="wax.FactoryBeanUser">
<property name="myFactoryBean" ref="&theFactoryBean"/>
</bean>
With this config Spring throws following exception on start:
[skipped irrelevant part]
Caused by: org.xml.sax.SAXParseException: The reference to entity "theFactoryBean" must end with the ';' delimiter.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:174)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:388)
at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(XMLScanner.java:1414)
I found this solution Spring: Getting FactoryBean object instead of FactoryBean.getObject(), this question is maked as answered and four people voted for it. So I assume that this solution might work, but currently there is something wrong in my code.
Second one, working but awkward:
public class FactoryBeanUser implements ApplicationContextAware{
private MyFactoryBean myFactoryBean;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
myFactoryBean = (MyFactoryBean)applicationContext.getBean("&theFactoryBean");
}
}
My question is it possible to make first approach functional or I should stick with a second way?
It seems the XML parser interprets the ampersand (&) as a start of an XML-entity. You can try using ref="&theFactoryBean".
The spring docs is not clear whether this syntax is allowed in an xml file, or only with programatic lookup. But then the xml configuration is used by the app context, so I assume the & should work (although it seems it has not been the best choice for a special symbol)
Here's why I'd suggest another thing - if you really need the factory bean rather than its product, create another bean, that does not implement FactoryBean, define a method createObject() or something like that, and use it in all factories that need it.
A sidenote - better reference the xsd with the version included:
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd