I want to make DataSource in Spring through JNDI. All the configuration are given.
Can someone tell me what is wrong with the configuration.
One thing I would like to mention here is that JNDI DS is hosted on JBoss server which does not host the Spring application.
Configuration
datasource-ds.xml
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<local-tx-datasource>
<jndi-name>jdbc/wc-mysql</jndi-name>
<connection-url>jdbc:mysql://xx.xx.xx.xx:3306/club</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<user-name>club</user-name>
<password>club</password>
<exception-sorter-class-name>
org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter
</exception-sorter-class-name>
<min-pool-size>5</min-pool-size>
<max-pool-size>20</max-pool-size>
<use-java-context>false</use-java-context>
<metadata><type-mapping>mySQL</type-mapping></metadata>
</local-tx-datasource>
</datasources>
configContext.xml
<bean id="wcDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/wc-mysql" />
<property name="jndiEnvironment">
<props>
<prop key="java.naming.provider.url">jnp://yy.yy.yy.yy:1099</prop>
<!--
<prop key="java.naming.factory.initial">
org.springframework.mock.jndi.SimpleNamingContextBuilder
</prop>
<prop key="java.naming.factory.url.pkgs">yourPackagePrefixesGoHere</prop> -->
<!-- other key=values here -->
</props>
</property>
<!-- other properties here-->
</bean>
Exception
Caused by: javax.naming.NameNotFoundException: Name jdbc is not bound in this Context
at org.apache.naming.NamingContext.lookup(NamingContext.java:770)
at org.apache.naming.NamingContext.lookup(NamingContext.java:153)
at org.apache.naming.SelectorContext.lookup(SelectorContext.java:152)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:154)
I have made few changes and Its now working fine.
A JNDI Template must be initialized with the JNP properties. And URL to JBoss server has to be in that properties.
configContext.xml
<bean id="wcJndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
<prop key="java.naming.provider.url">jnp://jndi.myURL.me:1099</prop>
<prop key="java.naming.factory.url.pkgs">org.jboss.naming:org.jnp.interfaces</prop>
<prop key="jnp.disableDiscovery">true</prop>
</props>
</property>
</bean>
<bean id="wcDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/wc-mysql"/>
<property name="resourceRef" value="false"/>
<property name="jndiTemplate" ref="wcJndiTemplate" />
</bean>
But after doing that changes I was facing an exception
java.lang.ClassNotFoundException: org.jnp.interfaces.NamingContextFactory
So I found a link mentioning to include a dependency of jbossall-client.jar in the POM to resolve the issue. So the pom changes are
<dependency>
<groupId>jboss</groupId>
<artifactId>jbossall-client</artifactId>
<version>4.2.2.GA</version>
</dependency>
Every thing seems to be working fine.
Thanks.
There is no problem with your remote JNDI as this line
<use-java-context>false</use-java-context>
will take care of it.
You have problem with your JNDI name value:
javax.naming.NameNotFoundException: Name jdbc is not bound in this Context
Change this in your applicationConfig.xml
<property name="jndiName" value="jdbc/wc-mysql" />
to
<property name="jndiName" value="java:/jdbc/wc-mysql"></property>
It should work
Related
I need on deployment schema generation for a webapp that uses JPA.
The server is Wildfly 9 with Hibernate as JPA provider.
I can achieve this by adding
<property name="hibernate.hbm2ddl.auto" value="create" />
to persistence.xml.
Is there another way to set this property per webapp and on deployment in Wildfly 9? I also tried hibernate.properties, but this had no effect.
There is no webapp specific deployment property out of the box.
But you can set a webapp specific system property which you reference in your persistence.xml:
<persistence-unit >
...
<properties>
<property name="hibernate.hbm2ddl.auto" value="${mywebapp.hibernate.hbm2ddl.auto}" />
</properties>
</persistence-unit>
A system property can be set in the standalone.conf(.bat) or in the standalone.xml:
<server xmlns="urn:jboss:domain:3.0">
<extensions> ... </extensions>
<system-properties>
<property name="mywebapp.hibernate.hbm2ddl.auto" value="create"/>
...
</system-properties>
...
</server>
Only drawback: you will have to set the system property in every environment - there is no default value.
Another option is to create an Integrator which sets the value in the settings. Unfortunately the config is read into the Settings object at the beginning and Settings.setAutoCreateSchema() and the other hibernate.hbm2ddl.auto specific properties are package protected, but you can set them with reflection:
public class AutoCreateSchemaIntegrator implements Integrator {
#Override
public void integrate(Configuration config, SessionFactoryImplementor factory,
SessionFactoryServiceRegistry registry) {
Settings settings = factory.getSettings();
try {
Method setter = settings.getClass().getDeclaredMethod("setAutoCreateSchema", boolean.class);
setter.setAccessible(true);
setter.invoke(settings, myDeploymentSpecificProperty);
} catch (ReflectiveOperationException | SecurityException e) {
// handle exception
}
}
}
You need to write the full qualified class name of that integrator into META-INF/services/org.hibernate.integrator.spi.Integrator:
com.myproject.AutoCreateSchemaIntegrator
This is the best option if you want to determine the hbm2ddl setting dynamically.
If you use Spring and JPA you can define all your persistence info in spring config xml. So you can include hibernate.hbm2ddl.auto to it. An example os Spring config file using org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean as EntityManagerFactory:
<!-- DataSource reachable by jndi, -->
<jee:jndi-lookup id="myDataSource" jndi-name="jdbc/XADatasource" expected-type="javax.sql.DataSource" />
<!-- jpa Properties used later in Hibernate configuration -->
<util:properties id="jpaHibernateProperties">
<prop key="hibernate.transaction.jta.platform">
org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform
</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<!-- validate | update | create | create-drop -->
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="javax.persistence.transactionType">JTA</prop>
<prop key="javax.persistence.validation.mode">AUTO</prop>
</util:properties>
<!-- Entity manager definition. No need of persistence.xml -->
<bean id="myEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
</bean>
</property>
<property name="packagesToScan">
<list>
<value>com.mycompany.myproject</value>
</list>
</property>
<property name="persistenceUnitName" value="myPU" />
<property name="jtaDataSource" ref="myDataSource" />
<!-- Hibernate specific params defined previously -->
<property name="jpaProperties" ref="jpaHibernateProperties" />
</bean>
For wildfly you can use the ${env} expression with a default value:
<property name="mywebapp.hibernate.hbm2ddl.auto" value="${env.DB_AUTO:validate}"/>
maybe I don't understand something correctly here. If one has configured the datasource like below
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close" p:driverClassName="${jdbc.driverClassName}"
p:url="${db.url}" p:username="${db.username}" p:password="${db.password}"
p:initialSize="10"
p:minIdle="10"
p:maxIdle="20"
p:maxActive="50"
p:timeBetweenEvictionRunsMillis="30000"
p:minEvictableIdleTimeMillis="60000"
p:validationQuery="SELECT 1"
p:validationInterval="30000" />
Does it make sense to add the following properties to the
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaProperties">
<props>
<prop key="hibernate.default_schema">${jdbc.schema}</prop>
<prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop>
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.generate_statistics">true</prop>
<prop key="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</prop>
<prop key="hibernate.cache.region_prefix"></prop>
<prop key="hibernate.cache.use_structured_entries">true</prop>
<prop key="hibernate.c3p0.minPoolSize">5</prop>
<prop key="hibernate.c3p0.maxPoolSize">20</prop>
<prop key="hibernate.c3p0.timeout">600</prop>
<prop key="hibernate.c3p0.max_statement">50</prop>
<prop key="hibernate.c3p0.testConnectionOnCheckout">true</prop>
</props>
</property>
If no. Which one is better?
In my mind, what I have configured above is the pool twice. Once with Tomcat JDBC and another with c3p0.
The benefit that Spring gives you in this case is that you can provide your own DataSource and use the connection pool implementation you want/need regardless where the environment your app will be deployed and thus your application will be completely independent of the application server (in this case, Tomcat that works as servlet container).
From this point on, it depends on you to decide which connection pool implementation to use. IMO I would recommend using HikariCP rather than C3P0 or Tomcat. Disclaimer: I don't support HikariCP by any means, I'm just a happy user of the technology.
If you want spring to get datasource from c3p0 pool, just make the LocalContainerEntityManagerFactoryBean refer the c3p0 datasource bean.Here is an example.
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
...
</bean>
<bean id="dataSource" class = "com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<!-- these are C3P0 properties -->
<property name="acquireIncrement" value="${c3p0.acquireIncrement}" />
<property name="minPoolSize" value="${c3p0.minPoolSize}" />
<property name="maxPoolSize" value="${c3p0.maxPoolSize}" />
<property name="maxIdleTime" value="${c3p0.maxIdleTime}" />
</bean>
You can config the properties as you wish.
You need to add c3p0 dependency into your project:
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version><!--Maybe this is not the newest version-->
<type>jar</type>
<scope>compile</scope>
</dependency>
I am wondering why don't you use JNDI to provide the data source?Tomcat as an example,in the $TOMCAT_HOME/Context.xml、Server.xml:
<Resource name="jdbc/sample" auth="Container"
type="com.mchange.v2.c3p0.ComboPooledDataSource"
username=...
password=...
url=...
driverClassName=...
otherAttributes...
/>
To reference the JNDI datasource please see here.
About the C3P0 pooling and spring see here and here.
Im trying to setup a Spring MVC web app using Hibernate ORM. Im using JBOSS AS.
There is a problem when Im trying to define a datasource bean:
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.databaseurl}" p:username="${jdbc.username}"
p:password="${jdbc.password}" />
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
When I run the app and access it via browser, it throws an exception -
org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.apache.commons.dbcp.BasicDataSource] for bean with name 'dataSource' defined in ServletContext resource [/WEB-INF/servletCtx.xml]; nested exception is java.lang.ClassNotFoundException: org.apache.commons.dbcp.BasicDataSource from [Module "deployment.untitled1.war:main" from Service Module Loader]
I've read somewhere that this datasource approach is old and deprecated. Is it true? What else would you suggest?
Thanks for hints and help.
java.lang.ClassNotFoundException means the required JAR file that contains org.apache.commons.dbcp.BasicDataSource is not available in classpath, just add it to fix the issue.
Instead of configuring it as a data-source use JNDI connection.
I was wondering how one would go about getting an object from a remote JNDI in Spring 3. Where do you specify the URL, how do you set it all up in a context file, etc. I have found some disperate information suggesting this is possible, but no singular source for how to do it for a JNDi that is on a different server.
You could use, for example, the JndiObjectFactoryBean class within a basic configuration like this one:
<bean id="someId" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="yourLookupNameGoesHere" />
<property name="jndiEnvironment">
<props>
<prop key="java.naming.provider.url">yourRemoteServerGoesHere:PortGoesHere</prop>
<prop key="java.naming.factory.initial">yourNamingContextFactoryGoesHere</prop>
<prop key="java.naming.factory.url.pkgs">yourPackagePrefixesGoHere</prop>
<!-- other key=values here -->
</props>
</property>
<!-- other properties here-->
</bean>
You can then specify other environment properties as needed and you can also simplify your configuration by using the Spring jee schema.
expanding on the above with an example for connecting to a remote activeMQ server in JBoss EAP7 using CAMEL Jms component.
You will need these 3 beans in your Spring XML application context:
<bean id="remoteQCF" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="${factoryJndiName}" />
<property name="jndiEnvironment">
<props>
<prop key="java.naming.provider.url">http-remoting://${remoteHost}:${remotePort}</prop>
<prop key="java.naming.factory.initial">org.jboss.naming.remote.client.InitialContextFactory</prop>
<!-- other key=values here <prop key="java.naming.factory.url.pkgs">yourPackagePrefixesGoHere</prop> -->
</props>
</property>
</bean>
<bean id="remoteQCFproxy"
class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
<property name="targetConnectionFactory" ref="remoteQCF" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</bean>
<bean id="jmsremote" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="remoteQCFproxy" />
</bean>
where each ${xxx} denotes a value that you shall supply in place or with a property placeholder in your application context.
If you do not need a user and password to open a JMS queue connection, you may omit the second bean and reference directly the first bean as connectionFactory in the Camel JmsComponent bean.
The 'jmsremote' bean can then be used in CAML URI's like "jmsremote:queue:myQueue1"
We are trying to upgrade from Spring 1.2.8 to Spring 3.0
However when we are trying to configure txManager for Websphere I always get a class cast exception.
We tried based on the example provided by IBM which doesn't work.
I am using WAS 7.0 and Spring.3.0.5 and hibernate.3.6.jars...
Here is the Spring config:
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="ewpDataSource" />
<property name="mappingResources">
<list>
<value>com/fme/example/model/Person.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.default_schema">ORIG</prop>
<prop key="hibernate.cglib.use_reflection_optimizer">false</prop>
<prop key="hibernate.use_sql_comments">true</prop>
<prop key="hibernate.transaction.factory_class">
org.hibernate.transaction.JTATransactionFactory
</prop>
<prop key="hibernate.transaction.manager_lookup_class">
org.hibernate.transaction.WebSphereExtendedJTATransactionLookup
</prop>
</props>
</property>
</bean>
<!-- Our Data source --->
<bean id="ewpDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/TOI_ORIG" />
</bean>
<!--- Get the Web sphere Specific TX manager -->
<bean id="transactionManager"
class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/>
</beans>
I read this article and tried exactly as specified.
http://www.ibm.com/developerworks/websphere/techjournal/0609_alcott/0609_alcott.html
And also tried
http://robertmaldon.blogspot.com/2006/09/using-websphere-transaction-manager.html
But we are getting this Exception.
Caused by: java.lang.IllegalStateException: Cannot convert value of type [org.springframework.transaction.jta.WebSphereUowTransactionManager] to required type [javax.transaction.TransactionManager] for property 'transactionManager': no matching editors or conversion strategy found
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:231)
at org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:447)
I see that the class
org.springframework.transaction.jta.WebSphereUowTransactionManager
provided for Websphere doesn't implement javax.transaction.TransactionManager any where in the hierarchy.
Any idea?
I got it working. In addition to the above hibernate settings here is what I did.
The object of type WebSphereUowTransactionManager is not an instance of
javax.transaction.TransactionManager
but there is superclass method inside WebSphereUowTransactionManager
called getTransactionManager()
this returns object of type javax.transaction.TransactionManager
<bean id="wasUOWTxnManagerObj"
class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/>
<!--
Now call get getTransactionManager on WebSphereUowTransactionManager
object.
-->
<bean id="tranSactionManager"
class="javax.transaction.TransactionManager"
factory-bean="wasUOWTxnManagerObj"
factory-method="getTransactionManager">
</bean>
With this change now you can use WebSphereUowTransactionManager. Hope this helps.
When using Spring you usually don't need to use javax.transaction.TransactionManager directly.
Use transaction management approaches provided by Spring instead, see 10. Transaction Management.