how to resolve org.springframework.beans.NotWritablePropertyException - spring

hi i am using spring config.xml to config my embedded database hsqldb. my spring config is as below:
<jdbc:embedded-database id="dataSource" type="HSQL">
<jdbc:script location="classpath:schema.sql" />
</jdbc:embedded-database>
<bean id="adapterDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="datasource" ref="dataSource"></property>
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:file:data/db/lmexadapter_db" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
when run run my appication which is using above spring config.xml it give me a exception as below:
org.springframework.beans.NotWritablePropertyException: Invalid property 'datasource' of bean class [org.apache.commons.dbcp.BasicDataSource]: Bean property 'datasource' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
please help to resolve this as soon as possible
Thank you

The issue is that org.apache.commons.dbcp.BasicDataSource doesn't have a "setDatasource" method. It does have a protected field "datasource", however, which you could expose by subclassing and providing a setter.

Related

spring Multi DataSource #Service annotation with existing error

I have a code that is an error in the Spring Framework
Error Cause I know
So I do not know how to solve it the question.
I am being used with mybatis library
I had multi DataSource of two Account DataBase
I created a root-context.xml
-----------------------root-context.xml -----------------------------------------------------------
Oracle Account 1 Test1
<bean id="dataSourceTest1" class="org.apache.commons.dbcp.BasicDataSource" destroy-m
ethod="close">
<property name="driverClassName" value="net.sf.log4jdbc.DriverSpy"/>
<property name="url" value="jdbc:log4jdbc:oracle:thin:#111.111.1111.1111:1111:Test1"/>
<property name="username" value="TEST1"/>
<property name="password" value="TEST1"/>
<property name="maxIdle" value="200"/>
<property name="maxActive" value="200"/>
<property name="minIdle" value="5"/>
</bean>
<bean id="sqlSessionFactoryTest1" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSourceTest1" />
<property name="mapperLocations" value="classpath*:test/service/server/test1/**/*.xml" />
</bean>
<bean id="sqlSessionTest1" class="org.mybatis.spring.SqlSessionTemplate" name="sqlSessionTest1">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactoryTest1" />
</bean>
<mybatis-spring:scan base-package="test.service.server.test1" template-ref="sqlSessionTest1" />
Oracle Account test2
<bean id="dataSourceTest2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="net.sf.log4jdbc.DriverSpy"/>
<property name="url" value="jdbc:log4jdbc:oracle:thin:#222.222.2222.222:2222:Test2"/>
<property name="username" value="Test2"/>
<property name="password" value="Test2"/>
<property name="maxIdle" value="200"/>
<property name="maxActive" value="200"/>
<property name="minIdle" value="5"/>
</bean>
<bean id="sqlSessionFactoryTest2" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSourceTest2" />
<property name="mapperLocations" value="classpath*:test/service/server/test2/**/*.xml" />
</bean>
<bean id="sqlSessionTest2" class="org.mybatis.spring.SqlSessionTemplate" name="sqlSessionTest2">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactoryTest2" />
</bean>
<mybatis-spring:scan base-package="test.service.server.test2" template-ref="sqlSessionTest2"/>
-----------------------root-context.xml END ---------------------------------------------------------
i am not used context:component-scan
<!-- <context:component-scan base-package="test.service.server.test1.test1service"/>-->
<!-- <context:component-scan base-package="test.service.server.test2.test2service"/>-->
I use the SpringJUnit4 each unit test
Were sequentially to (DataSourceTest and SqlSessionFactory Test and SqlSession Test mapperScanTest).
did not have any problems until mapperScanTest.
However, an error occurs when star using the annotation # Service
------------------------------------------service interface code ------------------------------------
public interface Test2_SERVICE {
public List<Test2_VO> GET_ListVO();
}
-------------------------------------------implement service code----------------------------------
#Service("Test2_SERVICE") *//<--Error annotaion*
public class Test2_SERVICEIMPLE implements Test2_SERVICE{
#Resource
Test2_MAPPER mapper;
#Override
public List<Test2_VO> GET_ListVO() {
return mapper.GET_ListMapperVO();
}
}
---------test Code------------------------------
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "file:src/main/**/*-context.xml" })
public class TestService {
Logger logger = Logger.getLogger(Thread.currentThread().getClass());
#Autowired
#Qualifier("Test2_SERVICE")
Test2_SERVICE test2_SERVICE;
#Override
public void testString() {
logger.info("---------------------");
List<Test2_VO> listVO = test2_SERVICE.GET_ListVO();
logger.info(listVO );
logger.info("---------------------");
}
}
Error Messages-----------------------------------
Caused by:
org.springframework.context.annotation.ConflictingBeanDefinitionException:
Annotation-specified bean name 'Test2_SERVICE' for bean class
[test.service.server.test2.test2service.Test2_SERVICE] conflicts with
existing, non-compatible bean definition of same name and class
[test.service.server.test2.test2service.Test2_SERVICEIMPLE]
------------------------------------------------end---------------------------------------------
#Service("Test2_SERVICE") *//<--Error annotaion*
The problem did not exist until the object Test2_MAPPER
However, the error begins in Test2_SERVICE
# Service ("Test2_SERVICE") Where there is only used here (Test2_SERVICEIMPLE).
Because of this problem
I am suffering for three days..
Somebody tell me solve the problem for this error message.
Thank you for reading my article.
The problem is that you create a bean with the name "Test2_SERVICE" for Test2_SERVICEIMPLE with this annotation:
#Service("Test2_SERVICE")
//creates the bean with id="TEST2_Service" of the type Test2_SERVICEIMPLE
public class Test2_SERVICEIMPLE implements Test2_SERVICE
and then assign exactly this Test2_SERVICEIMPLE bean to the interface Test2Service
#Autowired
#Qualifier("Test2_SERVICE")
//here you assign the bean of the not matching type Test2_SERVICEIMPLE to
//a variable of type Test2_SERVICE
Test2_SERVICE test2_SERVICE;
That means that the interface wants to use the bean for the implementation...
So just remove/change the #Qualifier("Test2_SERVICE") or change the name of the #Service("Test2_SERVICE")
How to autowire annotation qualifiers and how to name autodetected components

How to configure 2 databases in MyBatis using MyBatis-Spring

I am trying to configure 2 different datasources in my application as it is required.
My configuration in the AppContext.xml is as follows:
<bean id="dataSourceA" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.ibm.db2.jcc.DB2Driver"/>
<property name="url" value="datasourceAURL"/>
<property name="username" value="aaaa"/>
<property name="password" value="pppp"/>
</bean>
<bean id="dataSourceB" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.ibm.db2.jcc.DB2Driver"/>
<property name="url" value="datasourceBURL"/>
<property name="username" value="bbbb"/>
<property name="password" value="cccc"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com/ex/myBatis/mappings" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSourceA" />
<property name="typeAliasesPackage" value="com.ex.myBatis.entities"/>
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
<bean id="sqlSessionFactory1" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="configDataSource" />
<property name="typeAliasesPackage" value="com.ex.myBatis.entities"/>
</bean>
<bean id="sqlSession1" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory1" />
</bean>
<bean id="callService" class="com.ex.myBatis.Service.callService">
<property name="sqlSession" ref="sqlSession1" />
</bean>
But while accessing the bean I am getting the below Exception
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'callService': Injection of autowired
dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire method: public final void
org.mybatis.spring.support.SqlSessionDaoSupport.setSqlSessionTemplate(org.mybatis.spring.SqlSessionTemplate);
nested exception is
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No
qualifying bean of type [org.mybatis.spring.SqlSessionTemplate] is
defined: expected single matching bean but found 2:
sqlSession,sqlSession1
Please somebody help me in figuring out the issue.
Also please suggest me if there is someother way to configure 2 Datasources.
Your configuration is mostly correct. The problem you face is that you use autowiring to inject one of callService dependencies.
Seems that you use SqlSessionDaoSupport and its sqlSessionTemplate field is autowired. There are two templates defined so spring cannot automatically wire dependencies. You need specify correct template manually.

How to get spring bean reference to java field automatically

my spring XML is below,
<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://localhost:3306/test" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<bean id="jTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource" />
</bean>
I'm creating the spring bean context when the server is starting up. When I hit on the submit button of the JSP page, it should call the servlet and executes the SQL Query.
Without doing JdbcTemplate jTemplate = (JdbcTemplate)context.getBean("jTemplate") is there anyway I can get the jTemplate object automatically injected to my java property?
my java property is this,
private JdbcTemplate jTemplate;
So, simply I want to use the jTemplate without just doing JdbcTemplate jTemplate = (JdbcTemplate)context.getBean("jTemplate")
Sorry guys I'm bit new to Spring, If you don't get what I'm saying please ask me again.
Use autowiring which can be in three ways
By name
By Type
By Constructor
Further reading is available here
like one solution is
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" autowire="byName">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<bean name="jTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource" />
</bean>
Use #Autowired annotation to get this bean automatically like this.
#Autowired
private JdbcTemplate jTemplate;

heroku : java.lang.IllegalStateException: Cannot handle (64) '#'

I'm trying to deploying a java app to Heroku.
It use a enviroment variable such as postgres://foo:foo#heroku.com/hellodb to config database in the spring applicationcontext.xml https://devcenter.heroku.com/articles/spring-mvc-hibernate#modify_database_configuration
I follow the document,config it,and set the DATABASE_URL use set DATABASE_URL=postgres://postgres:huang#heroku.com/yan(windows).
But when i run it locally,i got a Error:
creating bean with name 'dataSource' defined in ServletContext resource [/WEB-INF/spring/applicationContext.xml]: Initialization of bean failed; nested exception is o
rg.springframework.beans.factory.BeanExpressionException: Expression parsing fai
led; nested exception is java.lang.IllegalStateException: Cannot handle (64) '#'
my spring xml is this:
`<bean class="java.net.URI" id="dbUrl">
<constructor-arg value="#{systemEnvironment['DATABASE_URL']}" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="url"
value="#{ 'jdbc:postgresql://' + #dbUrl.getHost() + #dbUrl.getPath() }" />
<property name="username" value="#{ #dbUrl.getUserInfo().split(':')[0] }" />
<property name="password" value="#{ #dbUrl.getUserInfo().split(':')[1] }" />
</bean>`
it seems the spring container cannot handle the '#' symbol ,but i really do not know how to deal it! I searched in google,but i got anything.
Does anyone know how to deal it ? thanks!
yeah,i fix it!!!
the official document has a error!!!
i just remove the "#" symbol,and it works
this spring xml is like this:
<bean class="java.net.URI" id="dbUrl">
<constructor-arg value="#{systemEnvironment['DATABASE_URL']}" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="url"
value="#{ 'jdbc:postgresql://' + dbUrl.getHost() + dbUrl.getPath() }" />
<property name="username" value="#{ dbUrl.getUserInfo().split(':')[0] }" />
<property name="password" value="#{ dbUrl.getUserInfo().split(':')[1] }" />
</bean>
i will write a letter to report this error

multiple databases with Spring Data JPA

I'm trying to use Spring Data JPA with 2 databases in project. But an exception is triggered when I'm trying to run the application:
07:21:47.734 [main] ERROR o.s.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'deviceRepository': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [javax.persistence.EntityManagerFactory] is defined: expected single bean but found 2
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:342) ~[spring-orm-3.1.0.RELEASE.jar:3.1.0.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106) ~[spring-beans-3.1.0.RELEASE.jar:3.1.0.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-3.1.0.RELEASE.jar:3.1.0.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) ~[spring-beans-3.1.0.RELEASE.jar:3.1.0.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294) ~[spring-beans-3.1.0.RELEASE.jar:3.1.0.RELEASE]
...
Here is my applicationContext.xml
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource1">
<property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${database.url1}"/>
<property name="username" value="${database.username1}"/>
<property name="password" value="${database.password1}"/>
<property name="testOnBorrow" value="true"/>
<property name="testOnReturn" value="true"/>
<property name="testWhileIdle" value="true"/>
<property name="timeBetweenEvictionRunsMillis" value="1800000"/>
<property name="numTestsPerEvictionRun" value="3"/>
<property name="minEvictableIdleTimeMillis" value="1800000"/>
<property name="validationQuery" value="SELECT 1"/>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager1">
<property name="entityManagerFactory" ref="entityManagerFactory1"/>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager1"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory1">
<property name="persistenceUnitName" value="persistenceUnit1"/>
<property name="dataSource" ref="dataSource1"/>
</bean>
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource2">
<property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${database.url2}"/>
<property name="username" value="${database.username2}"/>
<property name="password" value="${database.password2}"/>
<property name="testOnBorrow" value="true"/>
<property name="testOnReturn" value="true"/>
<property name="testWhileIdle" value="true"/>
<property name="timeBetweenEvictionRunsMillis" value="1800000"/>
<property name="numTestsPerEvictionRun" value="3"/>
<property name="minEvictableIdleTimeMillis" value="1800000"/>
<property name="validationQuery" value="SELECT 1"/>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager2">
<property name="entityManagerFactory" ref="entityManagerFactory2"/>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager2"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory2">
<property name="persistenceUnitName" value="persistenceUnit2"/>
<property name="dataSource" ref="dataSource2"/>
</bean>
Here is my DAO interface:
#Repository
public interface DeviceRepository extends JpaRepository<Device, DevicePK>,
JpaSpecificationExecutor<Device> {
}
I've read a lot about #PersistenceContext but I never saw usages with JpaRepository.
Well you do have 2 entitymanagers.
I've never used JPARepository, but if it works close to its counter parts on spring-data for nosql, Spring will enhance the class, and probably inject the EM on it. Your problem is that you have 2 EM declared.
Have a look at the spring-jpa docs, they'll show you how to configure the repository for how you can add specific EMF to your repos
Long story short:
You have to create custom implementation of that interface and that implementation has to contain entity manager declared as:
#PersistenceContext(unitName = "persistenceUnit1")
private EntityManager entityManager;
if you want to use persistence unit 1.
Check this out: http://docs.spring.io/spring-data/data-jpa/docs/current/reference/html/repositories.html#repositories.custom-implementations, it also has examples and example 1.17 (little bit down the page) implements interface and has entity manager in it and that entity manager is passed on to super constructor.
You may also take a look at Spring Data - JPA, customizing Repository not working, it has implementation of interface that extends JpaRepository and it also has entity manager declared in implementation. Just add unitName to #PersistenceContext annotation and try it that way.
You may not need any custom methods (so your interface can be empty) but you do need constructor that passes on entity manager and all that tinkering with extending your own interface to bypass default automatic wiring behaviour.
One of the two datasource must be defined as primary.
<bean> has a primary attribute that can be set to true or false:
<bean primary="true|false"/>
Usually in #Configuration the #Primary annotation is placed to:
EntityManager
DataSource
TransactionManager
So you can try to add primary="true"
to the following beans:
dataSource1
transactionManager1
entityManagerFactory1

Resources