Weird behaviour of import tag in spring's configuration file - spring

I am working on the spring spring-3.2.2. I have created two java projects in eclipse.
SpringTest
Testclasspath
SpringTest project is having the below beans.xml in which the one bean is defined.
<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.0.xsd">
<bean id="helloWorld" class="com.spring.HelloWorld" init-method="testUpdate" scope="prototype">
<property name="message" value="Hello World!"/>
</bean>
</beans>
I have created the jar springtest.jar of the project SpringTest and it is been added in the classpath of the project Testclasspath. Bean configuration file for the Testclasspath project is talentacquisition.xml and it is importing the beans.xml file of the Springtest project. Please find the below content of talentacquisition.xml
<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.0.xsd">
<import resource="Beans.xml"/>
<bean id="juggler" class="com.springaction.springidol.Juggler" />
</beans>
I am confused with behavior of the import tag in the talentacquisition.xml How it is able to locate the Beans.xml which is present in the jar (springtest.jar) in the classpath and able to load the beans? Why spring is not giving any error ? Don't I have to modify the import tag in the talentacqusition.xml to following
<import resource="classpath:Beans.xml"/>
If import is able to locate the file Beans.xml , then when should we use classpath: and classpath* :?

ResourceLoaders are responsible for how Spring loads the resource. From the reference manual
The location path or paths supplied to an ApplicationContext
constructor are actually resource strings, and in simple form are
treated appropriately to the specific context implementation.
ClassPathXmlApplicationContext treats a simple location path as a
classpath location. You can also use location paths (resource strings)
with special prefixes to force loading of definitions from the
classpath or a URL, regardless of the actual context type.
The ClassPathXmlApplicationContext you're instantiating "treats a simple location path as a classpath location", i.e. it treats "Beans.xml" as "classpath:Beans.xml". Similarly, FileSystemXmlApplicationContext would treat "Beans.xml" as "file:Beans.xml".
Section 6.7 of the manual has more details too.

Related

Spring not import all beans implementations from JARs

In jar file has interfrace ILogger.
Another jars has implementations ILogger. (Example one.jar:Logger1, two.jar:Logger2,...)In main file applicationContext.xml has line:
<import resource="classpath:META-INF/applicationContext.xml"/>
And each jar has local applicationContext.xml with description one bean.
I inject all logger implementattions:
#Autowired
List<ILogger> loggers;
But list has only one implementation (only Logger2).
If i explicitly indicate beans in main applicationContext.xml:
<bean id="logger1" class="demo.Logger1" />
<bean id="logger2" class="demo.Logger2" />
All work very good - list has all beans.
But I do not want to explicitly indicate all implementations.Is there a solution to my problem?
I did not have an asterisk after classpath. My worked import:
<import resource="classpath*:META-INF/applicationContext.xml"/>

No Spring Bean found in EJB with SpringBeanAutowiringInterceptor

I need some help: I have one EAR-File, containing one WAR-File, one EJB-Jar-File and some "shared" libs:
aopalliance-1.0.jar commons-logging-1.1.1.jar log4j-1.2.16.jar spring-aop-4.0.5.RELEASE.jar spring-beans-4.0.5.RELEASE.jar spring-context-4.0.5.RELEASE.jar spring-context-support-4.0.5.RELEASE.jar spring-core-4.0.5.RELEASE.jar spring-expression-4.0.5.RELEASE.jar
The War File has a Context initializer which find the spring config and loads everything well.
I now want to use another Spring Context for the EJB Jar.
My EJB is defined as
#Stateless(mappedName = "ejb/SpringRocks")
#RemoteHome(com.ibm.websphere.ola.ExecuteHome.class)
#Interceptors(SpringBeanAutowiringInterceptor.class)
public class WolaUseCaseOne {
#Autowired
private DummyService dummyService;
/* ...More stuff here */
Inside the EJB-JAR, there is also a 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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="myEjb" name="myEjb" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg value="classpath*:META-INF/spring/simpleEjb.xml" />
</bean>
</beans>
The simpleEjb.xml is is also inside the EJB-Jar and is defining a very simple Bean:
<?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="myDummyService" class="com.provinzial.beispielanwendung.batch.wola.DummyServiceImpl" />
</beans>
As described, the WEB Part works perfect, but when the EJB is called, the SpringBeanAutowiringInterceptor is called, but seems to do nothing. What do I have to do, to get a Spring Context created?! My hope was that it is initialized when the EJB is created. I created a Subclass of SpringBeanAutowiringInterceptor with some loggers, but the class is only created, no method is called !
What else do I have to do? Or does anybody have a valid EAR File example?
I think the Problem is that inside the EJB Module no context is initialized...
Greets
Timo
I was facing similar issue with my EJB (no WAR). This is what fixed mine,
I was missing the spring-aop jar on my classpath. I see you have it so good there.
In my ejb-jar.xml file, I set the meta-data flag to true so I did not get prompted on deployment to complete.
I set to "false" for one deployment to see what IBM generated for me. In the ejb-jar.xml it added the following (my MDB is named TaskMDB),
<assembly-descriptor>
<interceptor-binding>
<ejb-name>TaskMDB</ejb-name>
<interceptor-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</interceptor-class>
</interceptor-binding>
</assembly-descriptor>
<interceptors>
<interceptor>
<interceptor-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</interceptor-class>
<post-activate>
<lifecycle-callback-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</lifecycle-callback-class>
<lifecycle-callback-method>autowireBean</lifecycle-callback-method>
</post-activate>
<pre-passivate>
<lifecycle-callback-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</lifecycle-callback-class>
<lifecycle-callback-method>releaseBean</lifecycle-callback-method>
</pre-passivate>
<post-construct>
<lifecycle-callback-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</lifecycle-callback-class>
<lifecycle-callback-method>autowireBean</lifecycle-callback-method>
</post-construct>
<pre-destroy>
<lifecycle-callback-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</lifecycle-callback-class>
<lifecycle-callback-method>releaseBean</lifecycle-callback-method>
</pre-destroy>
</interceptor>
</interceptors>
Then I added what IBM generated (the assembly-descriptor and interceptors stanzas) back to my ejb-jar.xml and set the metadata-complete back to true.
Then it worked. Hope this helps.
Here is the full ejb-jar.xml
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar version="3.1" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd">
<display-name>ares-api-uow-ejb</display-name>
<enterprise-beans>
<message-driven id="TaskMDB">
<ejb-name>TaskMDB</ejb-name>
<ejb-class>something.api.uow.ejb.mdb.TaskMDB</ejb-class>
<messaging-type>javax.jms.MessageListener</messaging-type>
<transaction-type>Bean</transaction-type>
</message-driven>
</enterprise-beans>
</ejb-jar>

unable to reference Spring services in JUnit

i am running a Karaf container with a number of beans implementing the com.mycompany.foo.IMyBean interface. i refer to them as "child beans". each such "child" bean is registered as a service. i also have a single "parent" bean that rounds up all those "child" services by using osgi:list. everything works just fine in runtime. however, when i run a very simple JUnit scenario, i get the following exception:
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'BeanRefsList': Invocation of init method
failed; nested exception is java.lang.IllegalArgumentException:
Required 'bundleContext' property was not set.
this is the context.xml in my JUnit project:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd
">
<bean id="ChildBean"
class="com.mycompany.foo.ChildBean">
</bean>
<osgi:service id="ChildBeanService" ref="ChildBean" interface="com.mycompany.foo.IMyBean"/>
<osgi:list id="BeanRefsList" interface="com.mycompany.foo.IMyBean"/>
<bean id="ParentBean" class="com.mycompany.foo.ParentBean">
<property name="childBeans" ref="BeanRefsList"/>
</bean>
</beans>
the test class also contains the following annotation entries:
#org.junit.runner.RunWith(SpringJUnit4ClassRunner.class)
#org.springframework.test.context.ContextConfiguration("context.xml")
please let me know what i am doing wrong. thank you for your time!
The error message explains it pretty clearly. The line that says
<osgi:list id="BeanRefsList" interface="com.mycompany.foo.IMyBean"/>
Needs too look more like
<bean id="ParentBean" class="com.mycompany.foo.ParentBean">
<property name="childBeans" ref="BeanRefsList"/>
</bean>
Where the property "bundleContext" gets set properly. I'm not familiar with OSGI, so I don't know what class/object needs to be set here. But, that's what's missing.
I'm not sure what OSGI is looking for that's making it tell you "bundleContext" property is missing, but it sounds like both osgi:list and osgi:service use some kind of bundleContext property.
Have you specified all of the same imported schemas in jUnit that you did for your runtime context?

Loading util:properties with Spring Profile causes multiple occurrences of ID

I am using Spring(3.1) profiles to load property files vis util:properties:
<beans profile="local">
<util:properties id="myProps"
location="classpath:local.properties" />
</beans>
<beans profile="dev">
<util:properties id="myProps"
location="classpath:dev.properties" />
</beans>
And I invoke the profile via a runtime parameter(running on TC Server):-Dspring.profiles.active=local
But I get the error There are multiple occurrences of ID value 'myProps'
This was running previously with other bean definitions but once the util:properties was added I get the error.
Make sure your xsd declarations are using >= 3.1 versions for both beans and util namespaces:
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.1.xsd ">
Most likely cause of error would be forgetting to set util declaration to 3.1, if as you say this works for other beans but not those declared using util.

Overriding System property in Spring PropertyPlaceHolderConfigurer for integration testing

I'm using a System property to define the location for an environment-specific properties file. However, I would like to override that value to something different for integration tests.
Here's my production spring setup. I'm using a custom PropertyPlaceholderConfigurer to resolve some encrypted property file values, but that's not important here:
<-- Spring configuration in file service-spring-beans.xml -->
<bean class="com.mycompany.MyPropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:properties/${MY_ENVIRONMENT}/${MY_ENVIRONMENT}.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="false"/>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>
At runtime, we define the value of MY_ENVIRONMENT as a Java system property. This all works as expected. However, for integration tests, I would like to define MY_ENVIRONMENT as "inttest", so the integration-test specific property file properties/inttest/inttest.properties is loaded.
I've tried to use a spring context loaded by the integration-test to set up a String bean with the id MY_ENVIRONMENT:
<?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-3.1.xsd">
<context:component-scan base-package="com.mycompany.myclasses"/>
<bean class="java.lang.String" id="MY_ENVIRONMENT">
<constructor-arg value="inttest"/>
</bean>
<!-- this imports the production spring context -->
<import resource="classpath:service-spring-beans.xml"/>
</beans>
However, the value of MY_ENVIRONMENT is not resolved , and I get this error when running the integration tests.
Caused by:
org.springframework.beans.factory.BeanInitializationException: Could
not load properties; nested exception is
java.io.FileNotFoundException: class path resource
[properties/${MY_ENVIRONMENT}/${MY_ENVIRONMENT}.properties] cannot
be opened because it does not exist
How can I override MY_ENVIRONMENT at inttest time without passing a System property to the JVM?
Since I was using the maven surefire plugin to run integration tests, the simplest solution turned out to be setting the system property using the surefire plugin configuration, like this:
<configuration>
<systemPropertyVariables>
<MY_ENVIRONMENT>inttest</MY_ENVIRONMENT>
</systemPropertyVariables>
<!-- ... -->
<configuration>
Since you don't want to use profiles, you can create multiple contexts and just include the proper context files for what you want. So for integration testing you have have your application-context.xml and an integration-property-context.xml file while, in the prod environment you would include the application-context.xml with a production-property-context.xml file. I've seen this approach used heavily to switch datasources between dev and prod where dev would be a BasicDataSource implementation and the prod environment references a JDNI DataSource.
This approach will help you avoid ActiveProfiles, but you run in to the problem of managing duplicate beans possibly which ActiveProfiles really simplified down.
you could look at overriding your whole property placeholder implementation using active profiles. that is, the default (no profile) launches your property placeholder, but a test profile (e.g. 'test') could create a new test bean for the property placeholder.
one of the challenges with property placeholder is that its loaded at the very early stages of the application context startup, so a normal override bean may not work.

Resources