How to change Spring to use Datasource from Tomcat vs BasicDataSource? - spring

How to change Spring to use Datasource from Tomcat vs BasicDataSource? below is a copy of the bean I make in my XML. Can someone tell me how to access the tomcat datasource
<beans:bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource" >
<beans:property
name="driverClassName"
value="${database.driver}" />
<beans:property
name="url"
value="${database.url}" />
<beans:property
name="username"
value="${database.user}" />
<beans:property
name="password"
value="${database.password}" />
<beans:property
name="initialSize"
value="5" />
<beans:property
name="maxActive"
value="10" />
</beans:bean>

In spring you have to change the configuration that it takes the configuration from tomcat via JNDI
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/myNewDatasource" />
</beans>
Then you have to configure the connection within tomact and make it available though jndi.
For example you could put this in the tomcat context.xml (and of course you need to put the driver in the tomcat lib directory)
<Resource name="jdbc/myNewDatasource"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://SERVER:3306/DB?useUnicode=true&characterEncoding=utf8"
auth="Container" username="USERNAME" password="PASSWORD"
maxIdle="3" maxActive="15" maxWait="10000"
logAbandoned="true" removeAbandoned="true" removeAbandonedTimeout="60"
validationQuery="select 1" />

Related

Spring MVC database connection [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have to create a connection with database to insert certain values in Spring MVC but there is following error in my servlet-context.xml while creating the connection:
Multiple annotations found at this line: - Cannot locate BeanDefinitionParser for element [bean] - cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'bean'. - Configuration problem: Cannot locate BeanDefinitionParser for element [bean] Offending resource: file [E:/General Workspace/Spring Workspace/Record_mvc/ src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml]
I have declared bean with id="dataSource" but it seems to be not working. Could you help me to understand why it cannot find declaration for element 'bean' and what does it mean
"the matching wildcard is strict"
Here is the code for dispatcher. Thanks in advance.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing
infrastructure -->
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources
in the /WEB-INF/views directory -->
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.lead.mvc" />
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:8080/leadmanager" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<!-- <bean id="jdbcTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean> -->
</beans:beans>
OK, so the problem is that you didn't specify wildcard for bean, so you should write:
<beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:8080/leadmanager" />
<property name="username" value="root" />
<property name="password" value="root" />
</beans:bean>
And then is should work.

Spring with JPA not persisting objects

I have read many tutorials to config spring with JPA. I am using a local MySQL database and i have this context:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- DataSource Setup -->
<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/test" />
<property name="username" value="vitornobrega" />
<property name="password" value="" />
</bean>
<!-- Entity Manager Factory -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.vitornobrega.myapp.entities" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
</bean>
</property>
</bean>
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />
</beans>
I have a test on JUnit to test my DAO and works nice but when i try to persist an entity with this config, i never the in hibernate log the insert command but in test case i see it. If i try to make a entitymanager.flush i get an exception because any transaction is running.
What i should change to can make persist on my local database with this entities?
thanks
If i try to make a entitymanager.flush i get an exception because any transaction is running.
If I'm reading that right, the problem is you're trying to save something without starting a transaction. Transactions are required when changing persistent state.
In order to be able to persist in database it is mandatory to be within a transaction. So the better you can solve it is to annotate #Transactional ... e.g. on the method
This also make me crazy for couple of hours some time ago.
are you using annotations in your classes? if so please make sure you
<context:component-scan base-package="com.vitornobrega.myapp"> because arpart from the jpa configurations i can see where you are injecting your dependencies.

Change hibernate.connection.url from within Spring

I am using Hibernate in combination with Spring. As database I am currently using HSQL, which stores its data in a file (like SQLite). The path to the HSQL file is currently hard-coded in the persistence.xml. How can I access and change this value at runtime, so a user can load and save from/to an arbitrary HSQL file?
persistence.xml:
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="something-unit">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver" />
<property name="hibernate.connection.url" value="jdbc:hsqldb:file:~/something-db/somethingdb" />
<property name="hibernate.connection.username" value="sa" />
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
</persistence>
Spring applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:data="http://www.springframework.org/schema/data/jpa"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- Database Setup -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="something-unit" />
</bean>
<data:repositories base-package="com.something.playlist"/>
<!-- Transaction Setup -->
<tx:annotation-driven/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
</beans>
Thanks for any hint!
You can specify a JNDI datasource and pass it to Hibernate. Or you can define your own plugin strategy for obtaining JDBC connections by implementing the interface org.hibernate.connection.ConnectionProvider
For more hints see: http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/session-configuration.html
Edit 2/16: There is an example on StackOverflow on creating a custom ConnectionProvider: How can I set Datasource when I'm creating Hibernate SessionFactory?
If you are going to change the data source on the fly, rather than at the startup, you will have to restart the Hibernate session factory. To do it correctly, you will have to make sure that no transactions are running in it at the time of the restart. Following question/answers would help you with that: Hibernate Sessionfactory restart | Spring
A commonly used strategy is to define all runtime configurations in one or several *.properties files and use spring's PropertyPlaceholderConfigurer to load the values and substitute the placeholder in applicationContext.xml, read more here: Best ways to deal with properties values in XML file in Spring, Maven and Eclipses.
app.properties:
# Dadabase connection settings:
hibernate.connection.driver_class=org.hsqldb.jdbcDriver
hibernate.connection.url=jdbc:hsqldb:file:~/something-db/somethingdb
hibernate.connection.username=sa
hibernate.connection.password=changeit
hibernate.dialect=org.hibernate.dialect.HSQLDialect
hbm2ddl.auto=update
... ...
applicationContext-dataStore.xml:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<!-- Default location inside war file -->
<value>classpath:app.properties</value>
<!-- Environment specific location, a fixed path on deployment server -->
<value>file:///opt/my-app/conf/app.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true"/>
</bean>
... ...
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${hibernate.connection.driver_class}" />
<property name="url" value="${hibernate.connection.url}" />
<property name="username" value="${hibernate.connection.username}" />
<property name="password" value="${hibernate.connection.password}" />
</bean>
One problem here is the PropertyPlaceholderConfigurer doesn't parse persistence.xml, the solution is to move all hibernate configuration into Spring's applicationContext.xml, as it is not necessary to set them in persistence.xml. read more here: loading .properties in spring-context.xml and persistence.xml.
persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="JPAService" transaction-type="RESOURCE_LOCAL"/>
</persistence>
applicationContext-datSource.xml:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${hibernate.connection.driver_class}"/>
<property name="url" value="${hibernate.connection.url}"/>
<property name="username" value="${hibernate.connection.username}"/>
<property name="password" value="${hibernate.connection.password}"/>
</bean>
... ...
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:./META-INF/persistence.xml"/>
<property name="persistenceUnitName" value="JPAService"/>
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="${hibernate.dialect}"/>
<property name="showSql" value="true" />
<property name="generateDdl" value="true"/>
</bean>
</property>
<property name="jpaProperties">
<!-- set extra properties here, e.g. for Hibernate: -->
<props>
<prop key="hibernate.hbm2ddl.auto">${hbm2ddl.auto}</prop>
</props>
</property>
</bean>
Note that the web application need to be restarted every time you alter the configuration in /opt/my-app/conf/app.properties, in order to make changes take effect.
Hope this helps.
If you wish to use hibernate via the JPA Abstraction you can we-write your code or service to use an javax.persistence.EntityManagerFactory. Autowire one of these and call createEntityManager(Map map); You can provide a datasource in the map. You could wrap the entity manager with your own implementation that pulls the parameter off a thread-local for creating the datasource.
EDIT: Mis-read the context and saw you are using an EntityManagerFactory. In which case just read the last part where you wrap the Factory with a delegate that creates the correct datasource from a threadlocal.

Spring batch trying to create persistant Batch Job Respository again

This seems to be a stupid issue. I am trying to configure an Oracle10g database for Spring Batch Job Repository (Spring Batch 2.1.7), I was able to have the tables created using the script available at org/springframework/batch/core/schema-oracle10g.sql in core. I also set the property batch.data.source.init to false.
On a clean database my batch program runs fine, successfully creating all the Batch tables/Sequences and populating them with the details of the batch results. However, when I run it again Spring Batch tries to create these tables again and throws "ORA-00955: name is already used by an existing object" exception. What am I doing wrong?
# For Oracle
batch.jdbc.driver=oracle.jdbc.driver.OracleDriver
batch.jdbc.url=jdbc:oracle:thin:#localhost:1521:orcl
batch.jdbc.user=****
batch.jdbc.password=****
batch.schema=****
batch.schema.script=classpath:/org/springframework/batch/core/schema-oracle10g.sql
batch.drop.script=classpath:/org/springframework/batch/core/schema-drop-oracle10g.sql
batch.jdbc.testWhileIdle=true
batch.data.source.init=false
Following is my context file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.1.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:property-placeholder location="classpath:batch.properties" />
<context:component-scan base-package="com.myco.mypack" />
<jdbc:initialize-database data-source="dataSource">
<jdbc:script location="${batch.schema.script}" />
</jdbc:initialize-database>
<import resource="classpath:/META-INF/spring/module-context.xml" />
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" lazy-init="true">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="transactionManager"/>
<property name="databaseType" value="oracle" />
<property name="tablePrefix" value="BATCH_"/>
<property name="isolationLevelForCreate" value="ISOLATION_DEFAULT"/>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${batch.jdbc.driver}" />
<property name="url" value="${batch.jdbc.url}" />
<property name="username" value="${batch.jdbc.user}" />
<property name="password" value="${batch.jdbc.password}" />
</bean>
</beans>
i do not see the use of batch.data.source.init like this:
<jdbc:initialize-database data-source="dataSource"
enabled="${batch.data.source.init}">
<jdbc:script location="${batch.schema.script}" />
</jdbc:initialize-database>
It's been a while but i think for people searching for this problem it will help to know that you can disable creating the databases by using
spring.batch.initializer.enabled=false
in application.properties as given in the documentation:
http://docs.spring.io/spring-boot/docs/current/reference/html/howto-database-initialization.html
<jdbc:initialize-database data-source="dataSource"
enabled="${batch.data.source.init}">
<jdbc:script location="${batch.schema.script}" />
If I pass Command Line argument -Dbatch.data.source.init=false ,then the intialization is not enabled.
But If I use the below configuration and set enabled to false in the context xml , then initialisation is triggered even though enabled flag is false
<jdbc:initialize-database data-source="dataSource"
enabled="false">
<jdbc:script location="false" />

JNDI Resource Definition in Apache Tomcat 6

I'm more than inexperienced with Apache Tomcat, so forgive me if it's a trivial question I'm asking.
My task is to change a rather big program so that it uses the connection from Tomcat instead of its own bean, so that you don't have to rebuild the code when the database changes.
This is the original bean definition (slightly changed - passwords and such...):
<bean id="ProjectDS" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" scope="singleton">
<property name="url"
value="jdbc:as400://127.0.0.1/TEST2;prompt=false;naming=sql;errors=full;date format=usa;date separator=/;time format=hms;time separator=:;transaction isolation=read committed;"/>
<property name="driverClassName" value="com.ibm.as400.access.AS400JDBCDriver"/>
<property name="username" value="asdf"/>
<property name="password" value="asdf"/>
<property name="initialSize" value="${ProjectDS.initialSize}"/>
<property name="maxActive" value="${ProjectDS.maxActive}"/>
<property name="maxIdle" value="${ProjectDS.maxIdle}"/>
<property name="minIdle" value="${ProjectDS.minIdle}"/>
<property name="testOnBorrow" value="${ProjectDS.testOnBorrow}"/>
<property name="removeAbandoned" value="${ProjectDS.removeAbandoned}"/>
<property name="removeAbandonedTimeout" value="${ProjectDS.removeAbandonedTimeout}"/>
<property name="logAbandoned" value="${ProjectDS.logAbandoned}"/>
</bean>
After reading several tutorials about Tomcat configuration, I did the following:
The new bean:
<bean id="ProjectDS" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>ProjectDS</value>
</property>
<property name="resourceRef" value="true"></property>
</bean>
server.xml :
<Resource name="ProjectDS" global="ProjectDS" auth="Container"
type="org.apache.commons.dbcp.BasicDataSource"
driverClassName="com.ibm.as400.access.AS400JDBCDriver"
url="jdbc:as400://127.0.0.1/TEST2"
username="asdf"
password="asdf" />
context.xml:
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<ResourceLink global="ProjectDS" name="ProjectDS" type="org.apache.commons.dbcp.BasicDataSource"/>
What I get is:
Exception processing Global JNDI Resources
javax.naming.NamingException: Cannot create resource instance
I read somewhere that I shouldn't put the above into the server.xml but into the web.xml, but I don't know where exactly. Could that be the problem?
First, rollback your context.xml and server.xml in your tomcat and/or. Here is a working configuration:
Create a file in src/main/webapp/META-INF named context.xml which contains:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource name="ProjectDS" auth="Container"
type="javax.sql.DataSource"
driverClassName="com.ibm.as400.access.AS400JDBCDriver"
url="jdbc:as400://127.0.0.1/TEST2"
username="asdf"
password="asdf" />
</Context>
Then, edit your bean in this way:
<bean id="ProjectDS" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/ProjectDS" />
<property name="proxyInterface" value="javax.sql.DataSource" />
</bean>
Difference here is the java:comp/env/ProjectDS and the proxy unterface.
Hope it will work for you!

Resources