How to use a Spring config file in a Maven dependency - java

In dependency A I have the following:
<beans>
<bean
id="simplePersonBase"
class="com.paml.test.SimplePerson"
abstract="true">
<property
name="firstName"
value="Joe" />
<property
name="lastName"
value="Smith" />
</bean>
</beans>
And then in project B, I add A as a dependency and have the following config:
<?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="simplePersonAddress01"
parent="simplePersonBase">
<property
name="firstName"
value="BillyBob" />
<property
name="address"
value="1060 W. Addison St" />
<property
name="city"
value="Chicago" />
<property
name="state"
value="IL" />
<property
name="zip"
value="60613" />
</bean>
</beans>
When I use ClassPathXmlApplicationContext like so:
BeanFactory beanFactory = new ClassPathXmlApplicationContext( new String[] {
"./*.xml" } );
SimplePerson person = (SimplePerson)beanFactory.getBean( "simplePersonAddress01" );
System.out.println( person.getFirstName() );
Spring complains as it can not resolve the parent xml.
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'simplePersonBase' is defined
I am sure there is a way to do this, however, I have not found it. Does anyone know how?

Try with the classpath*: prefix.

Does A.jave have the corresponding xml file? In project A, did you the xml inside src/main/resources?

Not really an answer to the question - but beware of this approach.
It can be a nightmare resolve errors. Imagine getting an spring error on startup - the only way to resolve it is cracking open all the jars to find any application contexts held within.
At the very least put the application context files in a distinct package and specify any you wish to use by name.
A *.xml from the root of the classpath is a recipe for disaster.

Related

Error validating the file spring-ldap.xsd

i have this error in my bean configuration, but for another project works.. the 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:context="http://www.springframework.org/schema/context"
xmlns:ldap="http://www.springframework.org/schema/ldap"
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/ldap http://www.springframework.org/schema/ldap/spring-ldap.xsd">
but in one project i have this error:
referenced file contains error http://www.springframework.org/schema/ldap/spring-ldap.xsd
UPDATE:
i modify my beam like this and work (i added conf. for pooling but is not important):
<!-- LDAP config -->
<bean id="contextSourceTarget" class="org.springframework.ldap.core.support.LdapContextSource">
<property name="url" value="${ldap.url}" />
<property name="base" value="${ldap.base}" />
<property name="userDn" value="${ldap.userDn}" />
<property name="password" value="${ldap.password}" />
<property name="pooled" value="false" />
</bean>
<bean id="contextSource"
class="org.springframework.ldap.pool.factory.PoolingContextSource">
<property name="contextSource" ref="contextSourceTarget" />
</bean>
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSource" />
</bean>
I guess it's because Pivotal's site is displaying captcha before showing the actual XSD,
see Spring schemaLocation fails when there is no internet connection
It depends on whether you get the error in the IDE or in the runtime.
If it's a specialized XML editor you should refer to the documentation of your editor on how to override/specify schema location, if it's in the runtime likely you have to check your project dependencies(pom.xml if it's a maven project).
Spring uses its own mechanism to get the XSD in classpath library (runtime).
Uses following files
META-INF/spring.handlers (to parse tag xml to object by an Handler)
example of spring-core-3.2.2.jar
http://www.springframework.org/schema/c=org.springframework.beans.factory.xml.SimpleConstructorNamespaceHandler
http://www.springframework.org/schema/p=org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler
http://www.springframework.org/schema/util=org.springframework.beans.factory.xml.UtilNamespaceHandler
META-INF/spring.schemas (to identify the correct xsd used)
example of spring-core-3.2.2.jar
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd=org/springframework/beans/factory/xml/spring-beans-2.0.xsd
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd=org/springframework/beans/factory/xml/spring-beans-2.5.xsd
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd=org/springframework/beans/factory/xml/spring-beans-3.1.xsd
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd=org/springframework/beans/factory/xml/spring-beans-3.2.xsd
http://www.springframework.org/schema/beans/spring-beans.xsd=org/springframework/beans/factory/xml/spring-beans-3.2.xsd
http://www.springframework.org/schema/tool/spring-tool-2.0.xsd=org/springframework/beans/factory/xml/spring-tool-2.0.xsd
http://www.springframework.org/schema/tool/spring-tool-2.5.xsd=org/springframework/beans/factory/xml/spring-tool-2.5.xsd
http://www.springframework.org/schema/tool/spring-tool-3.0.xsd=org/springframework/beans/factory/xml/spring-tool-3.0.xsd
http://www.springframework.org/schema/tool/spring-tool-3.1.xsd=org/springframework/beans/factory/xml/spring-tool-3.1.xsd
http://www.springframework.org/schema/tool/spring-tool-3.2.xsd=org/springframework/beans/factory/xml/spring-tool-3.2.xsd
http://www.springframework.org/schema/tool/spring-tool.xsd=org/springframework/beans/factory/xml/spring-tool-3.2.xsd
http://www.springframework.org/schema/util/spring-util-2.0.xsd=org/springframework/beans/factory/xml/spring-util-2.0.xsd
http://www.springframework.org/schema/util/spring-util-2.5.xsd=org/springframework/beans/factory/xml/spring-util-2.5.xsd
http://www.springframework.org/schema/util/spring-util-3.0.xsd=org/springframework/beans/factory/xml/spring-util-3.0.xsd
http://www.springframework.org/schema/util/spring-util-3.1.xsd=org/springframework/beans/factory/xml/spring-util-3.1.xsd
http://www.springframework.org/schema/util/spring-util-3.2.xsd=org/springframework/beans/factory/xml/spring-util-3.2.xsd
http://www.springframework.org/schema/util/spring-util.xsd=org/springframework/beans/factory/xml/spring-util-3.2.xsd
The IDE want resolve the location of the XSD by schemaLocation, for this reason I suggest to remove XSD validation on your Eclipse.
Windows->Preferences->Validation-> "Suspend all validators"

Spring referring bean present in other xml using local attribute of ref tag

I am creating sample spring program to understand, local attribute of ref tag.
I have created two bean files
first one [applicationcontext.xml]
<bean class="org.vik.spring.SequenceGenerator" name="sequenceProperty_Other">
<property name="prefix">
<ref local="prefixGeneratorOther" />
</property>
<property name="suffix" value="23"></property>
</bean>
Second xml file [prefix_context.xml]
<bean class="org.vik.spring.DatePrefixGenerator" id="prefixGeneratorOther" p:prefix="other"/>
I have created app context like below
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("applicationcontext.xml" ,"prefix_context.xml");
When I request for bean "sequenceProperty_Other", spring successfully returns it
SequenceGenerator sequenceConstrutornerator = applicationContext.getBean( "sequenceProperty_Other",SequenceGenerator.class);
What I could understand from this, is that as "prefixGeneratorOther" bean in not in same xml file (applicationcontext.xml) and I am using local attribute to refer it, Spring should through exception. But in my case its working. Am I missing some thing.
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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- <bean class="org.vik.spring.SequenceGenerator" name="sequence"> </bean> -->
<bean class="org.vik.spring.DatePrefixGenerator" id="prefixGenerator"
p:prefix="122333">
</bean>
<bean class="org.vik.spring.SequenceGenerator" name="sequenceProperty_Locale">
<property name="prefix">
<ref local="prefixGenerator" />
</property>
<property name="suffix" value="23"></property>
</bean>
<bean class="org.vik.spring.SequenceGenerator" name="sequenceProperty_Other">
<property name="prefix">
<ref local="prefixGeneratorOther" />
</property>
<property name="suffix" value="23"></property>
</bean>
prefix_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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="org.vik.spring.DatePrefixGenerator" id="prefixGeneratorOther" p:prefix="other"/>
</beans>
Java class
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("applicationcontext.xml",
"prefix_context.xml");
System.out.println(applicationContext.getBean("prefixGenerator", PrefixGenerator.class).getPrefix());
SequenceGenerator sequenceProperty = applicationContext.getBean("sequenceProperty_Locale",
SequenceGenerator.class);
System.out.println(sequenceProperty);
SequenceGenerator sequenceConstrutornerator = applicationContext.getBean("sequenceProperty_Other",
SequenceGenerator.class);
System.out.println(sequenceConstrutornerator);
This particular behavior works with any version after Spring 3.1.0 (included) in the 3.x branch. If you test this with the latest 3.0.x (which is 3.0.7) you'll get an exception. If you test with Spring 4, you'll get an exception, but a different one.
If you take a look carefully at the exception in Spring 3.0.7, this refers to XML parsing:
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:243)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:347)
at org.springframework.beans.factory.xml.DefaultDocumentLoader.loadDocument(DefaultDocumentLoader.java:75)
which means the restriction is at xml schema level (and I believe it's at Java code level, as well).
This behavior has changed in Spring 3.1.0 (and after) because of this JIRA issue. From all those JIRA issue it is linked to, this one seems to explain what happened: the restriction has been eliminated from 3.1 schema and the ref local entered in a kind of "deprecated" state (because in 3.1.x and 3.2.x one can use it) and in Spring 4 ref local has been entirely eliminated. In Spring 4 the documentation says ref local is not supported anymore and, also, the xsd schema has been updated (in the sense that ref doesn't accept local anymore).

Spring beans understanding

What is the use of extends and parent attributes in spring bean file.
Is it related to a class extending another class. If some could share some thoughts around this it would be great. Some linke and examples would also be helpful.
The abstract and parent mechanism is used to keep your XML configuration DRY (Don't Repeat Yourself).
Consider you have 2 beans with 3 similar properties and 2 distinct.
Instead of repeating those 3 similar properties in both beans, you can do this:
make a bean that is abstract and holds those 3 common properties.
set the parent attribute on your 2 beans, to point to the abstract bean.
An example would be here.
<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="BaseCustomerMalaysia" class="com.mkyong.common.Customer" abstract="true">
<property name="country" value="Malaysia" />
</bean>
<bean id="CustomerBean" parent="BaseCustomerMalaysia">
<property name="action" value="buy" />
<property name="type" value="1" />
</bean>
</beans>

Passing jobParameters to bean in Spring Batch

I read a problem from the link https://stackoverflow.com/q/15784984/814074 and tried the solution given in above link.
However, I got the following error while running the code:
Error creating bean with name 'JobArgs' defined in class path resource [pipelineJob.xml]:
Initialization of bean failed; nested exception is org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type '$Proxy2 implementing java.io.Serializable,org.springframework.aop.scope.ScopedObject,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised' to required type 'com.test.genepanel.job.JobArguments' for property 'jobArguements'; nested exception is java.lang.IllegalStateException:
Cannot convert value of type [$Proxy2 implementing java.io.Serializable,org.springframework.aop.scope.ScopedObject,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [com.test.genepanel.job.JobArguments] for property 'jobArguements': no matching editors or conversion strategy found
The xml contains
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p"
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-3.0.xsd
http://www.springframework.org/schema/batch
http://www.springframework.org/schema/batch/spring-batch-2.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-2.5.xsd">
<batch:job id="pipelineJob">
<batch:step id="initializationStep" next="CleanUPStep">
<batch:tasklet ref="initializationStepTasklet" />
</batch:step>
<batch:step id="CleanUPStep">
<batch:tasklet ref="cleanupTaskLet" />
</batch:step>
</batch:job>
<bean id="basicStep" class="com.test.mutation.steps.BasicStep" abstract="true">
<property name="testJobArgs" ref="JobArgs"/>
</bean>
<bean id="JobArgs" class="com.test.mutation.application.TestJobArguements">
<property name="jobArguements" ref="jobArg">
</property>
</bean>
<bean id="jobArg" class="com.test.genepanel.job.JobArguments" scope="step">
<constructor-arg value="#{jobParameters['jobOutputDir']}"/>
</bean>
<bean id="emptyTaskLet" class="com.test.mutation.steps.EmptyStep" scope="step" parent="basicStep" />
<bean id="cleanupTaskLet" class="com.test.mutation.steps.CleanUpStep" scope="step" parent="basicStep">
</bean>
<bean id="initializationStepTasklet" class="com.test.mutation.steps.InitializationStep" scope ="step" parent="basicStep">
</bean>
</beans>
Am I missing anything?
The easy way to use step scope is like this:
<bean id="myReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
<property name="resource" value="file:#{jobParameters['input.file']}" />
<property name="linesToSkip" value="0" />
<property name="recordSeparatorPolicy" ref="simpleRecordPolicy" />
<property name="lineMapper" ref="journalSicIemtLineMapper" />
</bean>
Placing the step scope on the beans will delay his creation until the step it his referred is about to start. This is what Late-binding means, so you could access variables in the the ExecutionContext.
As the docs in the StepScope states:
beans with the StepScope will be aop:scoped-proxy. This means a proxy goes around the real object.
So when you define a regular Spring Beans (like you did with jobArg) and put the scope=step on it. You will have to find a way to retrieve the object inside this proxy when you want to set it in another bean (JobArgs)
I have looked all over the Spring references and I have not seen late binding in the constructor arguments so I am not sure it works. I assume you are setting the jobParameters in the JobArgs, in which case it should have the same scope="step"

How can i add a sub Tag to an Xml file already defined using Java?

I have an XML file that contains the configration of a Spring project and I want to dynamically add a new bean. I have to modify the initial xML file and add my new bean definition:
<?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="config"
class="myclass">
<property name="configXml">
<value>config.xml</value>
</property>
</bean>
<-- here a want to add a new bean definition <bean>....</bean> -->
</beans>
Has anyone got an idea?
I'm still not 100% what you mean, but here's two cases to try.
If you want to specify properties of a bean based on some derived value you can use the Spring Expression Language
http://static.springsource.org/spring/docs/3.0.x/reference/expressions.html
<bean id="someBean" class="example.SomeBean">
<property name="foo" value="#{config.whatever}"/>
</bean>
If you want to something more complex you can construct a bean programatically using a factory bean
<bean id="someBean" class="example.SomeBeanFactory">
<property name="config" ref="config"/>
</bean>
with something like
class SomeBeanFactory implements FactoryBean<SomeBean> {
public void setConfig(MyClass config) { ... }
public SomeBean getObject() {
...
}
}

Categories