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>
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 was trying to do generic way of implementation of DAO and I followed as per the Article
Following are my genericDaoImpl class
#SuppressWarnings("unchecked")
#Repository
public abstract class GenericDaoImpl<E, K extends Serializable>
implements GenericDao<E, K> {
#Autowired
private SessionFactory sessionFactory;
protected Class<? extends E> daoType;
/**
* By defining this class as abstract, we prevent Spring from creating
* instance of this class If not defined as abstract,
* getClass().getGenericSuperClass() would return Object. There would be
* exception because Object class does not hava constructor with parameters.
*/
public GenericDaoImpl() {
Type t = getClass().getGenericSuperclass();
ParameterizedType pt = (ParameterizedType) t;
daoType = (Class) pt.getActualTypeArguments()[0];
}
protected Session currentSession() {
return sessionFactory.getCurrentSession();
}
#Override
public void add(E entity) {
currentSession().save(entity);
}
#Override
public void saveOrUpdate(E entity) {
currentSession().saveOrUpdate(entity);
}
#Override
public void update(E entity) {
currentSession().saveOrUpdate(entity);
}
#Override
public void remove(E entity) {
currentSession().delete(entity);
}
#Override
public E find(K key) {
return (E) currentSession().get(daoType, key);
}
#Override
public List<E> getAll() {
return currentSession().createCriteria(daoType).list();
}
}
GENERICDAO
public interface GenericDao<E,K> {
public void add(E entity) ;
public void saveOrUpdate(E entity) ;
public void update(E entity) ;
public void remove(E entity);
public E find(K key);
public List<E> getAll() ;
}
SERVICE CLASS
#Service
public class test {
#Autowired
TestPlanDao testPlanDao;
#Transactional(propagation = Propagation.REQUIRED)
public int saveTestPlan()
{
try
{
TestPlan tp=new TestPlan();
tp.setTestplan_version(1);
testPlanDao.saveTestPlan(tp);
logger.info("testplan saved");
return 1;
}
catch(Exception e)
{
e.printStackTrace();
logger.error(e.getMessage(),e);
return 0;
}
}
This is my daoImpl
#Repository
public class TestPlanDaoImpl extends GenericDaoImpl<TestPlan, Integer> implements TestPlanDao{
#Override
#Transactional
public void saveTestPlan(TestPlan tp) {
// TODO Auto-generated method stub
add(tp);
}
hibernate configuration xml
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://${mysqlHost}/${mysqldatabase}" />
<property name="username" value="${mysqlUserName}" />
<property name="password" value="${mysqlPassword}" />
<property name="removeAbandoned" value="true" />
<property name="initialSize" value="20" />
<property name="maxActive" value="30" />
<property name="maxIdle" value="-1" />
<property name ="testOnBorrow" value="true"/>
<property name ="validationQuery" value="SELECT 1"/>
</bean>
<bean id="sessionFactoryConf"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.test.model.TestPlan</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.transaction.auto_close_session">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
I am not able to find the cause of
org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:106)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:988)
Did you try removing the following property :
<prop key="hibernate.transaction.auto_close_session">true</prop>
I believe that Hibernate will close the session too soon and resulting in your error. Since you use Spring TransactionManager, let it close the session.
you need to add following code in your hibernate configuration xml file
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<!-- property should be wired with a Hibernate SessionFactory in your case it is sessionFactoryConf -->
<property name="sessionFactory" ref="sessionFactoryConf" />
</bean>
You have to remove the #Transactional annotation from the Repository method , use only the #Transactional annotation on the service layer method.
#Repository
public class TestPlanDaoImpl extends GenericDaoImpl<TestPlan, Integer> implements TestPlanDao{
#Override
#Transactional //Remove annotation from here
public void saveTestPlan(TestPlan tp) {
// TODO Auto-generated method stub
add(tp);
}
Remove #Transactional annotation from function and use it on the class level.
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactoryConf" />
</bean>
This happens when you try to save changes on a Business Object after a transaction has already finished.
I think you should take a look to Spring Data JPA ? It has a lot more to offer than a generic DAO.
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
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.
consider the following code:
public abstract class MachineInPitImpl extends AbstractPersistentObject implements MachineInPit {
protected PersonReference currentOperatorRef;
public void setCurrentOperatorRef(PersonReference currentOperatorRef) {
this.currentOperatorRef = currentOperatorRef;
this.currentOperatorObj = null;
}
public PersonReference getCurrentOperatorRef() {
return currentOperatorRef;
}
The above class is not wired with spring context, I need to extend this class and grab the values in the get method of this class in my new class.
I have wrote a class as this:
public class MachineOPJMXBeanImpl extends MachineInPitImpl {
public MachineOPJMXBeanImpl(){
}
#Override
public PersonReference getCurrentOperatorRef() {
return super.getCurrentOperatorRef();
}
}
But the value in this class get method is null.Why am I getting null value?
Here is the applicationcontext.xml file:
<bean id="machineOPJMXBean"
class="com.mincom.works.cc.personnel.node.MachineOPJMXBeanImpl" parent="machineInPitImpl">
<property name="currentOperatorRef" ref="currentOperatorRef"/>
</bean>
<bean id="machineInPitImpl" class="minestar.pitlink.domain.pitmodel.MachineInPitImpl" abstract="true" scope="singleton" lazy-init="true">
<property name="currentOperatorRef" ref="currentOperatorRef"/>
</bean>
<bean id="currentOperatorRef" class="minestar.machinetracking.domain.PersonReference"/>