In Spring Batch, in the job-request.xml file you can have the chunk's writer run a "compositeItemWriter" which looks something like this:
<bean id="compositeItemWriter"
class="org.springframework.batch.item.support.CompositeItemWriter">
<property name="delegates">
<list>
<ref bean="writer1" />
<ref bean="writer2" />
</list>
</property>
</bean>
I was wondering if there's anything similar for readers? I tried using org.springframework.batch.item.support.CompositeItemStream but apparently delegates does not exist as a property. Putting "reader1" or "reader2" in the delegates property list in compositeItemWriter similarly does not work (cannot convert readers to writers)
Any advice would be greatly appreciated
Thanks!
MultiResourceItemReader reads items from multiple resources sequentially:
http://docs.spring.io/spring-batch/apidocs/org/springframework/batch/item/file/MultiResourceItemReader.html
It will look like:
<bean id="itemReader" class="org.springframework.batch.item.file.MultiResourceItemReader">
<property name="resources" value="LIST_OF_FILES" />
<property name="delegate" ref="itemReaderDelegate" />
</bean>
Related
It seems that the built in workflow activities are being executed twice. I am testing the checkout workflow and the DecrementInventoryActivity is removing the quantity from the sku twice.
Is this a known bug or am I doing something wrong?
I created the workflow like so:
<!-- Checkout Workflow Configuration -->
<bean id="blCheckoutWorkflow" class="org.broadleafcommerce.core.workflow.SequenceProcessor">
<property name="processContextFactory">
<bean class="org.broadleafcommerce.core.checkout.service.workflow.CheckoutProcessContextFactory"/>
</property>
<property name="activities">
<list>
<bean p:order="6000" id="blDecrementInventoryActivity" class="org.broadleafcommerce.core.checkout.service.workflow.DecrementInventoryActivity">
<property name="rollbackHandler" ref="blDecrementInventoryRollbackHandler" />
</bean>
<bean p:order="7000" id="blCompleteOrderActivity" class="org.broadleafcommerce.core.checkout.service.workflow.CompleteOrderActivity">
<property name="rollbackHandler" ref="blCompleteOrderRollbackHandler" />
</bean>
<bean p:order="9999999" class="com.mycompany.workflow.checkout.NotifyExternalInventorySystem" />
</list>
</property>
<property name="defaultErrorHandler">
<bean class="org.broadleafcommerce.core.workflow.DefaultErrorHandler">
<property name="unloggedExceptionClasses">
<list>
<value>org.broadleafcommerce.core.inventory.service.InventoryUnavailableException</value>
</list>
</property>
</bean>
</property>
</bean>
Starting with Broadleaf 4.0, the DecrementInventoryActivity was added by default to the blCheckoutWorkflow. See the 3.1.10-4.0.0 migration notes at http://www.broadleafcommerce.com/docs/core/4.0/migration-notes/3.1-to-4.0-migration/3.1.10-to-4.0-migration, in the section "Inventory Management".
This also goes for the defaultErrorHandler, and you can remove the blCompleteOrderActivity (that has always been managed in the framework). Basically, your customized blCheckoutWorkflow bean should change to:
<bean id="blCheckoutWorkflow" class="org.broadleafcommerce.core.workflow.SequenceProcessor">
<property name="activities">
<list>
<bean p:order="9999999" class="com.mycompany.workflow.checkout.NotifyExternalInventorySystem" />
</list>
</property>
</bean>
Starting with Broadleaf 3.0, any modifications to the blCheckoutWorkflow bean undergo the Broadleaf XML merging processing (which merges bean ids like blCheckoutWorkflow's list of activities). In your case, since the DecrementInventoryActivity is already defined in the core framework XML file and your definition of blCheckoutWorkflow merges with it, the final result is 2 instances of the DecrementInventoryActivity.
I asked a similar question, but based on the responses, I did a bad job describing what I am after. I have a spring 4 webapp that loads properties from a properties file. We consume those properties both via the "${proper.name"} expressions in spring, as well as by injecting a properties object into some of our classes.
We want to move most of the properties to a database table and make them reloadable. However, a few need to stay in local properties, potentially overriding the database setting. These should also be loaded dynamically after the app is running.
I know that once a particular bean is injected, it won't get reloaded, that doesn't concern me, it's up to that module to handle that. But I am having trouble getting the behavior I want. In particular, I have implemented an AbstractConfiguration from apache commons configuration to get the dual source and overriding I am after. But while it works for injecting the properties object, expressions loaded with "${prop.name}" don't work at all.
How can I get them to work? Did I override the wrong thing? Is it just some config detail?
<bean id="sysProperties" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="databaseConfigurator" />
<property name="targetMethod" value="getProperties"/>
</bean>
<bean id="databaseConfigurator" class="my.util.config.MyDatabaseConfigurator">
<property name="datasource" ref="dataSource" />
<property name="propertyFile" value="/WEB-INF/my.properties" />
<property name="applicationName" value="ThisApp" />
</bean>
<bean id="dbConfigFactory" class="org.apache.commons.configuration.ConfigurationConverter" factory-method="getProperties">
<constructor-arg ref="databaseConfigurator" />
</bean>
I haven't tested this, but I think it might work.
<bean id="sysProperties" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="databaseConfigurator" />
<property name="targetMethod" value="getProperties"/>
</bean>
<bean id="databaseConfigurator" class="my.util.config.MyDatabaseConfigurator">
<property name="datasource" ref="dataSource" />
<property name="propertyFile" value="/WEB-INF/my.properties" />
<property name="applicationName" value="ThisApp" />
</bean>
<bean name="PropertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="CommonsConfigurationFactoryBean"/>
</bean>
<bean name="CommonsConfigurationFactoryBean" class="org.springmodules.commons.configuration.CommonsConfigurationFactoryBean">
<constructor-arg ref="databaseConfigurator"/>
</bean>
I need to define a string value in Spring context XML file that is shared by multiple beans.
This is how I do it:
<bean id="aSharedProperty" class="java.lang.String">
<constructor-arg type="java.lang.String" value="All beans need me :)"/>
</bean>
Creating a java.lang.String bean by passing a constructor argument of java.lang.String seems kludgy.
Is there a shortcut?
I know this property can be passed using PropertyOverrideConfigurer, but I want to keep this property within the XML file.
You can use PropertyPlaceholderConfigurer and keep values in xml:
<context:property-placeholder properties-ref="myProperties"/>
<bean id="myProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties">
<props>
<prop key="aSharedProperty">All beans need me :)</prop>
</props>
</property>
</bean>
Then you reference it with:
<bean id="myBean" class="my.package.MyClass">
<property name="someField" value="${aSharedProperty}"/>
</bean>
A shorthand to the solution proposed by mrembisz goes like this:
<context:property-placeholder properties-ref="myProperties"/>
<util:properties id="myProperties">
<prop key="aSharedProperty">All beans need me :)</prop>
</util:properties>
You may be able to use the following:
<bean id="abstractParent" abstract="true">
<property name="sharedProperty" value="All child beans need me" />
</bean>
<bean id="bean1" class="MyClass1" parent="abstractParent">
...non-shared properties...
</bean>
<bean id="bean2" class="MyClass2" parent="abstractParent">
...non-shared properties...
</bean>
However, that relies on the property having the same name, so may not be applicable for you.
Something I've used in the past is SpEL to make sure that a bean has the same value as another:
<bean id="myBean" class="xxx.yyy.Foo" >
<property name="myProperty" value="1729" />
</bean>
<bean id="copyCat" class="xxx.yyy.Bar" >
<property name="anotherProperty" value="#{myBean.myProperty}" />
</bean>
I have found this to be particularly useful when setting the value did something other than a simple assignment.
We are trying to build some RESTful services with Spring MVC. We will be providing several representations: XML, HTML, & JSON. We would like to use JiBX as the OXM technology.
We are currently having difficulty figuring out how to wire up Spring with JiBX. If we want to wire up a single class, for example Customer, we simply define a JibxMarshaller, an XML MarshallingView, and add it too our ContentNegotiatingViewResolver. This works great.
The problem is we aren't sure how to wire up marshalling of multiple classes, for example, Customer and User. Each JibxMarshaller can support only one class (unlike the Jaxb2Marshaller which can support many). We tried declaring a marshaller for each class, but the MarshallingView only support one marshaller. Declaring multiple MarshallingViews does not work (it appears only the first one works).
Your advice is appreciated. Thanks.
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<util:map>
<entry key="xml" value="application/xml"/>
</util:map>
</property>
<property name="defaultViews">
<util:list>
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<property name="marshaller" ref="userMarshaller"/>
</bean>
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<property name="marshaller" ref="customerMarshaller"/>
</bean>
</util:list>
</property>
</bean>
<bean id="userMarshaller" class="org.springframework.oxm.jibx.JibxMarshaller">
<property name="targetClass" value="com.mycompany.User"/>
</bean>
<bean id="customerMarshaller" class="org.springframework.oxm.jibx.JibxMarshaller">
<property name="targetClass" value="com.mycompany.Customer"/>
</bean>
Update based on Ritesh's answer below:
It turns out that I was thrown off by the targetClass property of the JibxMarshaller. I thought it meant the marshaller would only work for a single class, however, it appears to just uses the target class as a way of finding all related bindings. So, the solution is to use just a single marshaller, using an arbitrary target class from your set of classes you have bindings for. For example:
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<util:map>
<entry key="xml" value="application/xml"/>
</util:map>
</property>
<property name="defaultViews">
<util:list>
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<property name="marshaller" ref="jibxMarshaller"/>
</bean>
</util:list>
</property>
</bean>
<bean id="jibxMarshaller" class="org.springframework.oxm.jibx.JibxMarshaller">
<property name="targetClass" value="com.mycompany.User"/>
</bean>
JiBX binding compiler adds JiBX_bindingList field to class files. At run time, the 'targetClass' (any compiled class with JiBX_bindingList field) is used to build a BindingFactory. It is the getMappedClasses() of IBindingFactory which is used by JibxMarshaller
in supports() method to check if marshaller can marshal a class.
Please also see JiBX runtime usage.
I'm trying to create an array of objects in a Spring context file so I can inject it to a constructor that's declared like this:
public RandomGeocodingService(GeocodingService... services) { }
I'm trying to use the <array> tag:
<bean id="googleGeocodingService" class="geocoding.GoogleGeocodingService">
<constructor-arg ref="proxy" />
<constructor-arg value="" />
</bean>
<bean id="geocodingService" class="geocoding.RandomGeocodingService">
<constructor-arg>
<array value-type="geocoding.GeocodingService">
<!-- How do I reference the google geocoding service here? -->
</array>
</constructor-arg>
</bean>
I haven't been able to find an example or something in the in the documentation on how to do this. Also, you have any suggestions for a better way of acheiving what I'm trying to do, please let me know :).
That's because there's no such thing as <array>, there's only <list>.
The good news is that Spring will auto-convert between lists and arrays as required, so defined your array as a <list>, and Spring will be coerce it into an array for you.
This should work:
<bean id="googleGeocodingService" class="geocoding.GoogleGeocodingService">
<constructor-arg ref="proxy" />
<constructor-arg value="" />
</bean>
<bean id="geocodingService" class="geocoding.RandomGeocodingService">
<constructor-arg>
<list>
<ref bean="googleGeocodingService"/>
</list>
</constructor-arg>
</bean>
Spring will also coerce a single bean into a list, if required:
<bean id="geocodingService" class="geocoding.RandomGeocodingService">
<constructor-arg>
<ref bean="googleGeocodingService"/>
</constructor-arg>
</bean>
Spring can automatically convert a list into an array[]
check it out http://forum.springsource.org/showthread.php?37767-Injecting-String-Array
<bean name="test" class="Test">
<property name="values" value="hugo,emil"></property>
</bean>
Check out the util schema.
I'm actually using <array> tag to inject an array of objects into a bean and it works.
Take a look at the following code...
<bean id="song1" class="mx.com.company.songs.Song">
<property name="name" value="Have you ever seen the rain?"/>
</bean>
<bean id="song2" class="mx.com.company.songs.Song">
<property name="name" value="La bamba"/>
</bean>
<bean id="guitarPlayer" class="mx.com.company.musician.GuitarPlayer">
<property name="songs">
<array>
<ref bean="song1"/>
<ref bean="song2"/>
</array>
</property>
</bean>