Override xml-defined spring bean in java-based configuration - java

I'm extending a complete product called Hippo CMS with my own REST interface. Hippo CMS is using Apache CXF for rest and acquires resources definitions from a spring bean defined somewhere in Hippo CMS sources. This definition look like this:
<bean id="jaxrsRestPlainResourceProviders" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="org.apache.commons.collections.ListUtils" />
<property name="targetMethod" value="union" />
<property name="arguments">
<list>
<ref bean="customRestPlainResourceProviders" />
<ref bean="defaultRestPlainResourceProviders" />
</list>
</property>
</bean>
<bean id="defaultRestPlainResourceProviders" class="org.springframework.beans.factory.config.ListFactoryBean">
<property name="sourceList">
<list>
</list>
</property>
</bean>
<!-- Default empty list of custom plain resource providers to be overriden. -->
<bean id="customRestPlainResourceProviders" class="org.springframework.beans.factory.config.ListFactoryBean">
<property name="sourceList">
<list>
</list>
</property>
</bean>
I need to override customRestPlainResourceProviders bean with my own bean. It works fine from XML configuration looking like this:
<bean id="customRestPlainResourceProviders" class="org.springframework.beans.factory.config.ListFactoryBean">
<property name="sourceList">
<list>
<bean class="org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider">
<constructor-arg>
<bean class="com.xxx.rest.FolderStructureResource"/>
</constructor-arg>
</bean>
</list>
</property>
</bean>
But it doesn't work if I define a bean in Java configuration class (which in the case of other beans works completely fine):
#Bean(name = "customRestPlainResourceProviders")
public ListFactoryBean customRestPlainResourceProviders() {
ListFactoryBean listFactoryBean = new ListFactoryBean();
listFactoryBean.setSourceList(
Lists.newArrayList(
new SingletonResourceProvider(
new FolderStructureResource(repository())
)
)
);
return listFactoryBean;
}
Is there a way to override a bean defined in XML configuration with a bean created in Java configuration class?

What version of spring are you using? I believe this issues is addressed in 4.2.

Related

How to set up property in Java hibernate configuration?

I currently have hibernate bean set up in an legacy package that is using XML:
<bean name="returnsDao" class="com.mycompany.HibernateReturnsDAO">
<property name="sessionFactory" ref="myhqSessionFactory" />
</bean>
<bean id="myhqSessionFactory" name="myhqSessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource">
<ref bean="myDataSource" />
</property>
<property name="hibernateProperties">
<ref bean="myHibernateProperties" />
</property>
<property name="annotatedClasses">
<list>
<value>com.mycompany.HibernateReturnsDAO</value>
</list>
</property>
</bean>
How do I create the beans in Java configuration from another package? I am trying to use the legacy package and my current package use Java config to initialize beans.
I tried the following and I am getting NPE at sessionFactory.getCurrentSession(), I suspect the Java config didn't set the property attribute properly, but how do I set up in Java config?
#Bean
public HibernateReturnsDAO returnDAO() {
return new HibernateReturnsDAO();
}
Have a look at Hibernate documentation for programmatic configuration

Broadleaf Commerce - My workflow activities are being executed twice

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.

How to enable ActiveMQ embedded kahadb using bean configuration

I need to enable local persistence of activemq embedded broker by enabling kahadb. How can i configure kahadb in bean xml file.
<bean id="producerBroker" class="org.apache.activemq.broker.BrokerService" init-method="start" destroy-method="stop">
<property name="brokerName" value = "producerBroker"/>
<property name="persistent" value="true"/>
<property name="transportConnectorURIs">
<list>
<value>tcp://localhost:7005</value>
</list>
</property>
<property name="jmsBridgeConnectors">
<list>
<bean class="org.apache.activemq.network.jms.JmsQueueConnector">
<property name="outboundQueueConnectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="http://localhost:8090" />
</bean>
</property>
<property name="outboundQueueBridges">
<list>
<bean class="org.apache.activemq.network.jms.OutboundQueueBridge">
<constructor-arg value="qvsample"/>
</bean>
</list>
</property>
</bean>
</list>
</property>
</bean>
EDIT
ActiveMQ's default persistence db is kahoDb. this line <property name="persistent" value="true"/>made this. I need to know how to change this db to another. Moreover i need a good reference to configure spring xml file for activemq?
You can create a bean of org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter and inject it into your broker through persistenceAdapter property.
E.g.
<bean id="persistenceAdapter" class="org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter">
<property name="directory" value="D:\test"/>
</bean>
<bean id="producerBroker" class="org.apache.activemq.broker.BrokerService" init-method="start" destroy-method="stop">
<property name="persistenceAdapter" ref="persistenceAdapter"/>
</bean>
You can use any other persistence adapter (e.g. leveldb) as long as it implements org.apache.activemq.store.PersistenceAdapter

Is there a way to get all registered message-converters?

I would like to somehow inject all HttpMessageConverter instances registered in Spring-MVC. I can successfully inject all that have been registered via.
private HttpMessageConverter[] converters;
#Autowired
public void setConverters(HttpMessageConverter[] converters) {
this.converters = converters;
}
However this only injects if the converter was registered inside the context (i.e. if defined outside of <annotation-driven>).
I did figure I would try using <beans:ref inside the <annotation-driven><message-converters> but it is not supported in spring-web 3.1.
Is there some class I can inject that may have a property I could use to get converters? Ideally I'd like to see the order in the filter chain they are registered in too.
You are right, the message converters are directly instantiated within the RequestMappingHandlerAdapter registered using the <mvc:annotation-driven/> xml tag, and the message-converters subtag explicitly expect the bean to be defined inline.
However, a workaround is to define the handler adapter and inject in the converters this way:
<bean name="handlerAdapter" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="webBindingInitializer">
<bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="conversionService" ref="conversionService"></property>
<property name="validator">
<bean class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"></property>
</bean>
</property>
</bean>
</property>
<property name="messageConverters">
<list>
<ref bean="byteArrayConverter"/>
<ref bean="jaxbConverter"/>
<ref bean="jsonConverter"/>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.ResourceHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"></bean>
</list>
</property>
</bean>
<bean name="byteArrayConverter" class="org.springframework.http.converter.ByteArrayHttpMessageConverter"></bean>
<bean name="jaxbConverter" class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"></bean>
<bean name="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
<bean name="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="useSuffixPatternMatch" value="false"></property>
</bean>
Spring puts all the converters behind an implementation of org.springframework.core.convert.ConversionService . You need to inject an instance of that interface into your class, you can read more in the spring documentation (including an example of how to inject it).
You can try injecting a bean of type RequestMappingHandlerAdapter but depending on your configuration, you might not have an instance!

Upgrading to springframework.scheduling.concurrent?

As of Spring 3.0 the ScheduledTimerTask is deprecated and I can't understand how to upgrade to org.springframework.scheduling.concurrent.
<bean id="timerFactoryBean" class="org.springframework.scheduling.timer.TimerFactoryBean">
<property name="scheduledTimerTasks">
<list>
<ref bean="onlineTimeSchedule" />
</list>
</property>
</bean>
<bean id="onlineTimeSchedule" class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="timerTask" class="com.example.OnlineTimerTask" />
</property>
<property name="period" value="60000" />
<property name="delay" value="1000" />
</bean>
Where the OnlineTimerTask extends java.util.TimerTask. It's simple task which publishes a message to publisher every minute. I checked the documentation, but nothing.. I can't understand which way to use from the concurrent package and which suits the best.
Also I want to turn this xml into #Bean in Java.
EDIT: So I tried to implement the xml with #Bean and #Configuration instead and here is what I got.
#Configuration
public class ContextConfiguration {
#Bean
public ScheduledExecutorFactoryBean scheduledExecutorFactoryBean() {
ScheduledExecutorFactoryBean scheduledFactoryBean = new ScheduledExecutorFactoryBean();
scheduledFactoryBean.setScheduledExecutorTasks(new ScheduledExecutorTask[] {onlineTimeSchedule()});
return scheduledFactoryBean;
}
#Bean
public ScheduledExecutorTask onlineTimeSchedule() {
ScheduledExecutorTask scheduledTask = new ScheduledExecutorTask();
scheduledTask.setDelay(1000);
scheduledTask.setPeriod(60000);
scheduledTask.setRunnable(new OnlineTimerTask());
return scheduledTask;
}
}
Will the code above be correct replacement for xml? Will in my case the setScheduledExecutorTasks work properly? I mean will the referencing to the same bean instance, if onlineTimeSchedule() is called more than once, will work here?
scheduledFactoryBean.setScheduledExecutorTasks(new ScheduledExecutorTask[] {onlineTimeSchedule()});
Use org.springframework.scheduling.concurrent.ScheduledExecutorFactoryBean in place of org.springframework.scheduling.timer.TimerFactoryBean and use org.springframework.scheduling.concurrent.ScheduledExecutorTask in place of org.springframework.scheduling.timer.ScheduledTimerTask. You will need to adjust the property names and values as needed but, that should be pretty self evident.
Optionally, you could refactor your com.example.OnlineTimerTask to not extend java.util.TimeTask as the ScheduledTimerTask only requires a runnable.
Spring 4 configuration - Below configuration working after spring migration from 3.2.x to 4.6.x
<bean id="schedulerTask"
class="org.springframework.scheduling.support.MethodInvokingRunnable">
<property name="targetObject" ref="springJmsListnerContainer" />
<property name="targetMethod" value="execute" />
</bean>
<bean id="timerTask" class="org.springframework.scheduling.concurrent.ScheduledExecutorTask">
<property name="runnable" ref="schedulerTask" />
<property name="delay" value="100" />
<property name="period" value="60000" />
</bean>
<bean class="org.springframework.scheduling.concurrent.ScheduledExecutorFactoryBean">
<property name="scheduledExecutorTasks">
<list>
<ref bean="timerTask" />
</list>
</property>
</bean>
The answer is - add one "runnable" field
<bean id="scheduledExecutorTask"
class="org.springframework.scheduling.concurrent.ScheduledExecutorTask">
<!-- wait 10 milli seconds before starting repeated execution -->
<property name="delay">
<value>10</value>
</property>
<!-- run every 1 second -->
<property name="period">
<value>1000</value>
</property>
<property name="runnable">
<ref bean="checkInvokingTask"/>
</property>
</bean>

Categories

Resources