Spring annotation based SAP connector - java

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.

Related

How to adapt xml bean into spring boot

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;
}
}

#Value Annotation and a Database PropertyPlaceHolderConfigurer

I've got two PropertyPlaceHolderConfigurer in my Spring XML. The first one obtains application properties from a file. The second one obtains user properties from database and looks like this:
<myConfiguration>
<bean id="databaseProperties"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="properties">
<bean class="org.apache.commons.configuration.ConfigurationConverter"
factory-method="getProperties">
<constructor-arg>
<ref bean="propertiesSource" />
</constructor-arg>
</bean>
</property>
</bean>
<bean id="propertiesSource" class="org.apache.commons.configuration.DatabaseConfiguration">
<constructor-arg type="javax.sql.DataSource" ref="tomcatDataSource" />
<constructor-arg value="application_properties" />
<constructor-arg value="PROPERTY_KEY" />
<constructor-arg value="PROPERTY_VALUE" />
</bean>
<bean id="propertiesService" class="com.xxx.PropertiesServiceImpl">
<property name="propertiesSource" ref="propertiesSource"></property>
</bean>
<myConfiguration>
It works properly and I can access to these properties injecting 'propertiesService' like:
#Autowired
private PropertiesService propertiesService;
Which is:
public class PropertiesServiceImpl implements PropertiesService {
#Autowired
private DatabaseConfiguration propertiesSource;
private Properties properties;
#Override
public String getProperty(String key) {
if (properties == null) {
properties = ConfigurationConverter.getProperties(propertiesSource);
}
return properties.getProperty(key);
}
#Override
public Properties getProperties() {
if (properties == null) {
properties = ConfigurationConverter.getProperties(propertiesSource);
}
return properties;
}
The problem is that I like to use #Value annotation but it does not work.
I've tried:
private #Value("#{propertiesService.helloWorld}") String helloWorld;
And, of course, the property exists and is reachable through 'propertiesService' but it results in the next error:
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 18): Property or field 'helloWorld' cannot be found on object of type 'com.infraportal.model.properties.PropertiesServiceImpl' - maybe not public?
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:224)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:94)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.access$000(PropertyOrFieldReference.java:46)
at org.springframework.expression.spel.ast.PropertyOrFieldReference$AccessorLValue.getValue(PropertyOrFieldReference.java:374)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:88)
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:120)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:242)
at org.springframework.context.expression.StandardBeanExpressionResolver.evaluate(StandardBeanExpressionResolver.java:161)
Which makes me think that Spring is looking for a 'getHelloWorld()' method instead using 'getProperty(String key)'
Any suggestion?
You need to explicitly specify which method is to be invoked, on bean referred in EL, and supply the argument value as below
#Value("#{propertiesService.getProperty('helloWorld')}")
private String helloWorld;
#Value: It is used for expression-driven dependency injection.
If you want to use with below example.
sample code
#Configuration
#PropertySource("classpath:jdbc.properties")
public class AppConfig {
#Value("${jdbc.driverClassName}")
private String driverClassName;
#Value("${jdbc.url}")
private String jdbcURL;
#Value("${jdbc.username}")
private String username;
#Value("${jdbc.password}")
private String password;
.....
..
}

Autowire annotation working in Controller but not anywhere else?

I am using Spring 4.1.1.
I have the following in my spring-dispatcher-servlet.xml
<context:component-scan base-package="com.au.controller,com.au.util" />
<mvc:resources location="/" mapping="/**" />
<mvc:annotation-driven />
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/caballocation" />
<property name="username" value="root" />
<property name="password" value="1234" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="AddImplDao" class="com.au.dao.AddressDaoImpl" />
I have the following controller class in package com.au.controller
#Controller
public class ControllerMain {
#Autowired
AddressDao obj;
#RequestMapping(value = "/test")
public #ResponseBody String test(){
//logger.debug("getWelcome is executed!");
obj.select();
return "1";
}
}
In the above code obj.select works as it gets autowired.
But the following class which is in com.au.util package have the value null of the object which is autowired.
public class DistanceCalculator {
#Autowired
AddressDao obj1;
public String calculate(String from, String to) throws IOException, JSONException {
..
Map output = obj1.calc(from, to);
..
}
Obj1 is null while execution. Getting java.lang.NullPointerException at obj1.calc(from,to)
Following is the interface and its implementation.
AddressDao.java
public interface AddressDao {
public void select();
public Map calc(String from,String to);
}
AddressDaoImpl.java
public class AddressDaoImpl implements AddressDao {
#Autowired
private JdbcTemplate jdbcTemplate;
private SimpleJdbcCall simpleJdbcCall;
#Autowired
public void setDataSource(DataSource dataSource) {
this.simpleJdbcCall = new SimpleJdbcCall(dataSource).withProcedureName("CheckForValuesInDB");
}
#Override
public void select() {
// TODO Auto-generated method stub
}
#Override
public Map calc(String from, String to) {
// TODO Auto-generated method stub}
What is the reason behind this?
you have to add extra space in com.au.controller,com.au.util so it should look like 'com.au.controller, com.au.util'. As for now only com.au.controller is scanned by your configuration.
//Edit
There should be #Component annotation in DistanceCalculator class

Invoke static method from spring config

Is it possible to invoke static method in Spring configuration file?
public MyClass {
public static void staticMethod() {
//do something
}
}
<bean id="myBean" class="MyClass">
<!-- invoke here -->
</bean>
When the static method creates an instance of MyClass you an do it like this
config
<bean id="myBean" class="MyClass" factory-method="staticMethod">
<!-- invoke here -->
</bean>
code
public static MyClass staticMethod() {
//create and Configure a new Instance
}
If you want the method only to be called on bean instantiation spring can't do it this way.
config
<bean id="myBean" class="MyClass" init-method="init">
<!-- invoke here -->
</bean>
code
public static void staticMethod() {
//create and Configure a new Instance
}
public void init() {
staticMethod();
}
try this
<bean id="b1" class="org.springframework.beans.factory.config.MethodInvokingBean">
<property name="staticMethod" value="MyClass.staticMethod" />
</bean>
see http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/config/MethodInvokingBean.html
Try something like this:
<!-- call static method -->
<bean id="test" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="MyClass" />
<property name="targetMethod" value="staticMethod" />
<property name="arguments">
<list>
<value>anArgument</value>
</list>
</property>
</bean>
Remove arguments as you might not need them.
Taken from https://gist.github.com/bulain/1139874
I was needing to call a static method. The above code worked fine.
This might be useful as well: How to make spring inject value into a static field.
If you are using annotations for spring configuration you can add the following method into your #Configuration class:
#Bean
public MethodInvokingFactoryBean methodInvokingFactoryBean() {
MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
methodInvokingFactoryBean.setStaticMethod("MyClass.staticMethod");
return methodInvokingFactoryBean;
}

Instantiating an object from bean using constructor args and refs

I've a class which takes in 2 Object Injections. 1 of them is to be injected through other bean ref whereas the other injected based on bean call. I want to instantiate an object using spring. How can I do this ?
I tried doing this:
MyBean Class:
class MyBean{
Injection1 ijn1;
MyBean(Injection1 ijn1,Injection2 ijn2){
this.ijn1=ijn1;
this.ijn2=ijn2;
}
}
Beans.xml
<bean name="myBean" class="MyBean" scope="prototype">
<constructor-arg>
<null />
</constructor-arg>
<constructor-arg>
<ref bean="injection2" />
</constructor-arg>
</bean>
<bean name="injection2" class="Injection2">
</bean>
Application Code:
MyBean getMyBean(Injection ijn1) {
return (MyBean)context.getBean("myBean", new Object[] { ijn1 })
}
But this doesn't works.
Any tips ?
You code doesn't work because spring looks for a MyBean's constructor like MyBean(Injection1 ijn1); you have to pass injection2 in this way.
MyBean getMyBean(Injection ijn1) {
return (MyBean)context.getBean("myBean", new Object[] { ijn1, context.getBean("injection2") })
}
If you want to use your code another way is to have partial inject in this way:
class MyBean{
Injection1 ijn1;
Injection2 ijn2;
MyBean(Injection1 ijn1){
this.ijn1=ijn1;
}
public void setIjn2(Injection2 ijn2I ) {
this.ijn2 = ijn2;
}
}
and in xml
<bean name="myBean" class="MyBean" scope="prototype">
<property name="inj2" ref="injection2" />
</bean>
<bean name="injection2" class="Injection2">
</bean>

Categories