I have an interceptor written in XML:
<bean class ="com.packt.webstore.interceptor.AuditingInterceptor"/>
<bean class ="com.packt.webstore.interceptor.PromoCodeInterceptor" >
<property name="promoCode" value ="OF3RTA"/>
<property name="errorRedirect" value="invalidPromoCode"/>
<property name ="offerRedirect" value ="products"/>
</bean >
How do I write the same thing in Spring Boot? I tried this:
#Bean
PromoCodeInterceptor promoCodeInterceptor() {
PromoCodeInterceptor promoCodeInterceptor = new PromoCodeInterceptor();
promoCodeInterceptor.setPromoCode("OF3RTA");
promoCodeInterceptor.setErrorReidect("invalidPromoCode");
promoCodeInterceptor.setOfferRedirect("products");
return promoCodeInterceptor;
}
But it doesn't work.
///edit
And what about this one?
<bean id="productValidator"
class="com.packt.webstore.validator.ProductValidator">
<property name="springValidators">
<set>
<ref bean = "unitsInStockValidator"/>
</set >
</property>
</bean >
<bean id ="unitsInStockValidator" class
="com.packt.webstore.validator.UnitsInStockValidator"/>
This code is ok?
#Bean
public ProductValidator productValidator() {
ProductValidator productValidator = new ProductValidator();
productValidator.setSpringValidators(unitsInStockValidator());
return productValidator;
}
#Bean
public UnitsInStockValidator unitsInStockValidator() {
UnitsInStockValidator unitsInStockValidator = new UnitsInStockValidator();
return unitsInStockValidator;
}
#Bean annotations working only in classes marked with #Configuration.
Create new class and put your bean definition in it
#Configuration
public class MyConfig {
#Bean
public PromoCodeInterceptor promoCodeInterceptor() {
PromoCodeInterceptor promoCodeInterceptor = new PromoCodeInterceptor();
promoCodeInterceptor.setPromoCode("OF3RTA");
promoCodeInterceptor.setErrorReidect("invalidPromoCode");
promoCodeInterceptor.setOfferRedirect("products");
return promoCodeInterceptor;
}
}
Related
I read, that in XML-based Spring configuration beans can inherit factory method.
I tried to implement it:
Controller interface:
public interface Controller {
String method();
}
ControllerFactory class:
public class ControllerFactory {
public Controller getController(String controllerName){
switch(controllerName){
case "OtherController":
return new OtherController();
case "SampleController":
return new SampleController();
default:
throw new IllegalArgumentException("Wrong controller name.");
}
}
}
SampleController implementation:
public class SampleController implements Controller {
#Override
public String method() {
return "SampleController";
}
}
OtherController implementation:
public class OtherController implements Controller {
#Override
public String method() {
return "OtherController";
}
}
But the following XML configuration:
<!--factory method inheritance -->
<bean id="controllerFactory" class="factory.ControllerFactory"/>
<bean id="parentController" abstract="true" factory-bean="controllerFactory" factory-method="getController"/>
<bean id="otherController" parent="parentController">
<constructor-arg index="0" value="OtherController"/>
</bean>
Gives compile-time error:
No matching constructor found in class 'Controller'
How can I change it to have factory method bean inheritance implemented properly?
Copying factory-method configuration to child bean works as expected:
<bean id="otherController" parent="parentController" factory-bean="controllerFactory" factory-method="getController">
<constructor-arg index="0" value="OtherController"/>
</bean>
Change bean with id parentController as follows:
<bean id="parentController" class="factory.ControllerFactory" factory-bean="controllerFactory" factory-method="getController">
<constructor-arg index="0" value="OtherController"/>
</bean>.
Try this it may work.
I'm trying to move from a xml based config to java annotations
I need your help getting this to work:
Obviously I can't set the RemoteJco interface to my SapConnector but what can I do to get this xml-config working?
#Bean
public RmiProxyFactoryBean jcoPool(){
RmiProxyFactoryBean jcoPool = new RmiProxyFactoryBean();
jcoPool.setServiceUrl("rmi://localhost/CH");
jcoPool.setServiceInterface(RemoteJco.class);
jcoPool.setRefreshStubOnConnectFailure(true);
return jcoPool;
}
#Bean
public SapConnector SapConnector(){
SapConnector sapConnector = new SapConnector();
sapConnector.setJcoPool(jcoPool());
return sapConnector;
}
this in the XML-Config works just fine:
<!-- JCO-Pool RMI Service -->
<bean id="jcoPool" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl" value="rmi://localhost/CH"/>
<property name="serviceInterface" value="com.itensis.jco.common.RemoteJco"/>
<property name="refreshStubOnConnectFailure" value="true" />
</bean>
<bean id="SapConnector" class="com.itensis.core.SapConnector">
<property name="jcoPool">
<ref bean="jcoPool" />
</property>
</bean>
this is my SAP-Connector
#Service
public class SapConnector {
#Autowired private RemoteJco jcoPool;
public RemoteJco getJcoPool() {
return jcoPool;
}
public void setJcoPool(RemoteJco jcoPool) {
this.jcoPool = jcoPool;
}
}
You have to make some changes on the jcoPool bean:
#Bean
public RemoteJco jcoPool(){
RmiProxyFactoryBean jcoPool = new RmiProxyFactoryBean();
jcoPool.setServiceUrl("rmi://localhost/CH");
jcoPool.setServiceInterface(RemoteJco.class);
jcoPool.setRefreshStubOnConnectFailure(true);
jcoPool.afterPropertiesSet();
return (RemoteJco) jcoPool.getObject();
}
Make sure that you return value has the same class as you used as service interface. And you have to call afterPropertiesSet() before calling getObject on the RmiProxyFacotoryBean instance.
applicationContext
<bean id="contentRegisteringBean" parent="abstractRegisteringBean" lazy-init="false">
<property name="processor">
<bean class="com.somepackage.ContentService$Processor"/>
</property>
</bean>
<bean id="abstractRegisteringBean" class="test.spring.MockFactoryBean">
<property name="type" value="com.somepackage.ProcessorRegisteringBeanImpl"/>
</bean>
ProcessorRegisteringBeanImpl
public class ProcessorRegisteringBeanImpl {
private Processor mProcessor;
public Processor getProcessor() {
return mProcessor;
}
public void setProcessor(final Processor processor) {
mProcessor = processor;
}
}
MockFactoryBean.java
public class MockFactoryBean<T> implements FactoryBean<T> {
private Class<T> type;
public void setType(Class<T> type) {
this.type = type;
}
#Override
public T getObject() throws Exception {
return Mockito.mock(type);
}
#Override
public Class<T> getObjectType() {
return type;
}
#Override
public boolean isSingleton() {
return true;
}
}
Exception:
org.springframework.beans.NotWritablePropertyException: Invalid
property 'processor' of bean class
[test.spring.MockFactoryBean]: Bean property 'processor' is
not writable or has an invalid setter method. Does the parameter type
of the setter match the return type of the getter?
When you declare a FactoryBean, Spring expects that you configure properties of the FactoryBean rather than properties of the object it creates.
Try the following instead:
<bean id="contentRegisteringBean" parent="abstractRegisteringBean" lazy-init="false">
<!-- Define concrete class to pass to Mockito.mock() -->
<constructor-arg value = "com.somepackage.ProcessorRegisteringBeanImpl" />
<property name="processor">
<bean class="com.somepackage.ContentService$Processor"/>
</property>
</bean>
<!-- Abstract definition of beans created using Mockito.mock() -->
<bean id="abstractRegisteringBean" abstract = "true"
class="org.mockito.Mockito" factory-method = "mock">
</bean>
Which is the properly way to translate this bean:
<bean id="artifactBinding" class="org.springframework.security.saml.processor.HTTPArtifactBinding">
<constructor-arg ref="parserPool"/>
<constructor-arg ref="velocityEngine"/>
<constructor-arg>
<bean class="org.springframework.security.saml.websso.ArtifactResolutionProfileImpl">
<constructor-arg>
<bean class="org.apache.commons.httpclient.HttpClient">
<constructor-arg>
<bean class="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager"/>
</constructor-arg>
</bean>
</constructor-arg>
<property name="processor">
<bean class="org.springframework.security.saml.processor.SAMLProcessorImpl">
<constructor-arg ref="soapBinding"/>
</bean>
</property>
</bean>
</constructor-arg>
</bean>
<bean id="soapBinding" class="org.springframework.security.saml.processor.HTTPSOAP11Binding">
<constructor-arg ref="parserPool"/>
</bean>
from XML to Java-Config?
You can also narrow the scope of the required collaborator object by forming
#Bean
public HTTPArtifactBinding artifactBinding(ParserPool parserPool, VelocityEngine velocityEngine) {
return new HTTPArtifactBinding(parserPool, velocityEngine, artifactResolutionProfile());
}
If Spring can resolve the parserPool and velocityEngine, then it can inject into your #Bean def method.
#Configuration
public class Configuration {
#Autowired
private ParserPool parserPool;
#Autowired
private VelocityEngine velocityEngine;
#Bean
public HTTPArtifactBinding artifactBinding() {
return new HTTPArtifactBinding(parserPool, velocityEngine, artifactResolutionProfile());
}
private ArtifactResolutionProfile artifactResolutionProfile() {
final ArtifactResolutionProfile artifactResolutionProfile = new ArtifactResolutionProfile(new HttpClient(new MultiThreadedHttpConnectionManager()));
artifactResolutionProfile.setProcessor(new SAMLProcessorImpl(soapBinding()));
return artifactResolutionProfile;
}
#Bean
public HTTPSOAP11Binding soapBinding() {
return new HTTPSOAP11Binding(parserPool);
}
}
I have:
#Component
class MyDecorator{
private Cache cache;
/*
some wrapped methods like get put remove
*/
}
Is it possible to autowire MyDecorator in different places with different cache?
I can configure XML like this:
<bean id="id1" class="MyDecorator ">
<property name="cache" value="Cache1" />
</bean>
<bean id="id2" class="MyDecorator ">
<property name="cache" value="Cache2" />
</bean>
But is there more elegance way without addition of xml configs, only with annotation?
Correct code should be
#Configuration
public class AppConfig {
#Bean
public MyAdapter adaptedCache2() {
return new MyAdapter (cache1);
}
#Bean
public MyAdapter adaptedCache2() {
return new MyAdapter (cache2);
}}
according to specs will be generated two beans adaptedCache1 and adaptedCache2
and now i can
autowire those beans with qualifiers adaptedCache1 and adaptedCache2
With Java configuration (Spring 3.1) you can write:
#Bean
public MyDecorator decoratedCache1() {
return new MyDecorator(cache1);
}
#Bean
public MyDecorator decoratedCache2() {
return new MyDecorator(cache2);
}
Of course in this case MyDecorator does not need #Component:
#Component
class MyDecorator{
private final Cache cache;
public MyDecorator(Cache cache) {
this.cache = cache;
}
}