I have a working programm with MySQL, Spring and a tomcat server, but the database connection is in spring-database.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<bean id="baseController" class="com.afterguard.sailplanner.controller.BaseController">
<property name="dao" ref="daoImpl" />
</bean>
<bean id="daoImpl" class="com.afterguard.sailplanner.dao.DaoImpl">
<property name="dataSource" ref="dataSource" />
</bean>
<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/sailplanner" />
<property name="username" value="sailplanner" />
<property name="password" value="sailplanner2" />
</bean>
</beans>
In order to deploy this program on a server now, I would need bring this database connection to the server, e.g. the context.xml oder server.xml.
How do I do I setup my tomcat 7 server to connect to the database and tell my application, that the database connection is setup in the tomcat?
You have to create a dataSource with JNDI :
First, in your spring bean configuration (spring-database.xml) add this :
<beans:bean id="dbDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<beans:property name="jndiName" value="java:comp/env/jdbc/myDB"/>
</beans:bean>
Second, create the jndi resource in the file apache-tomcat/conf/server.xml :
<Resource name="jdbc/globalDB"
global="jdbc/globalDB"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/sailplanner"
username="sailplanner"
password="sailplanner2"/>
Finally, create the resource link in the file apache-tomcat/conf/context.xml :
<ResourceLink name="jdbc/myDB"
global="jdbc/globalDB"
auth="Container"
type="javax.sql.DataSource" />
For Sql Server I do the following configuration:
You must be using Tomcat to manage connections. To do so we will be adding data sources to the TOMCAT_HOME/conf/context.xml file
<Context>
<Resource
name="jdbc/Oltp1"
auth="Container"
type="javax.sql.DataSource"
driverClassName="net.sourceforge.jtds.jdbc.Driver"
url="jdbc:jtds:sqlserver://localhost:3306/sailplanner"
username=user
password=password
testOnBorrow="true"
testOnConnect="true"
validationQuery="SELECT 1"
removeAbandoned="true"
removeAbandonedTimeout="30"
/>
</Context>
SQL Server JDBC driver (jtds-version.jar) must be copied to the TOMCAT_HOME/lib folder (if it is not there already)
If there are multiple data sources (OLTP1, OLTP2, etc) we will be adding multiple <Resource/> tags
You will be using the following JNDI names to name our data sources:
jdbc/Oltp1 – main OLTP database
jdbc/Oltp2 – secondary database
You will be configuring data sources so connection pool will know how to test connections and what to do with closed connections:
testOnBorrow="true"
testOnConnect="true"
validationQuery="SELECT 1"
removeAbandoned="true"
removeAbandonedTimeout="30"
Tomcat must be restarted when new resource is added or existing resource is modified.
application.properties file
Important! This file is deployed as a part of the classpath (src/main/resources/application.properties), not the external application.properties with externalized properties deployed to the TOMCAT_HOME/conf
You will be added the following property to this file:
spring.datasource.jndi-name=java:comp/env/jdbc/Oltp1
You need to remove all other spring.datasource properties from the application.properties if any exist
Important! You had to remove all spring.datasource properties from the external configuration file (application.properties deployed to the COMCAT_HOME/conf)
the database connection properties you should put in a property file and and depending upon your requirement you can change values in property file
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClass" value="${jdbc.driverClassName}" />
<property name="jdbcUrl" value="${jdbc.databaseurl}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
the property file
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.databaseurl=jdbc:mysql://localhost:3306/sailplanner
jdbc.username=root
jdbc.password=root
and to include this file in xml use
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="locations">
<list>
<value>classpath:applications.properties</value>
</list>
</property>
</bean>
Related
I am creating an embedded ActiveMQ in Tomcat by the below context.xml. It specifies the config xml location in the broker url brokerURL="vm://localhost?brokerConfig=xbean:activemq.xml".
I have put the activemq.xml at the base of my WAR file (so right next to WEB-INF in the WAR). Will it be found there?
MyWAR.war
WEB-INF/
beans.xml
activemq.xml
My context.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<!-- JMS Factory and Queue -->
<Resource auth="Container"
name="jms/ConnectionFactory"
type="org.apache.activemq.ActiveMQConnectionFactory"
description="JMS Connection Factory"
factory="org.apache.activemq.jndi.JNDIReferenceFactory"
brokerURL="vm://localhost?brokerConfig=xbean:activemq.xml"
brokerName="MyBroker"
useEmbeddedBroker="true"
trustAllPackages="true"
persistent="true"
/>
<Resource auth="Container"
name="jms/MyQueue"
type="org.apache.activemq.command.ActiveMQQueue"
description="Downtime Event JMS queue"
factory="org.apache.activemq.jndi.JNDIReferenceFactory"
physicalName="MyQueue"
persistent="true"
/>
<Resource auth="Container"
name="jms/MyQueueRetry"
type="org.apache.activemq.command.ActiveMQQueue"
description="Downtime Event JMS queue"
factory="org.apache.activemq.jndi.JNDIReferenceFactory"
physicalName="MyQueueRetry"
persistent="true"
/>
</Context>
EDIT: my updated activemq.xml:
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.apache.org/schema/core"
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.xsd http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
<bean id="ioExceptionHandler" class="org.apache.activemq.util.DefaultIOExceptionHandler">
<property name="ignoreAllErrors"><value>true</value></property>
</bean>
<!-- MySql DataSource Sample Setup -->
<bean id="mysql-ds" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/activemq"/>
<property name="username" value="testuser"/>
<property name="password" value="password"/>
<property name="poolPreparedStatements" value="true"/>
</bean>
<broker
xmlns="http://activemq.apache.org/schema/core"
persistent="true"
ioExceptionHandler="#ioExceptionHandler"
useShutdownHook="true"
useJmx="false"
brokerName="EventBroker"
>
<persistenceAdapter>
<jdbcPersistenceAdapter dataSource="#mysql-ds" />
</persistenceAdapter>
</broker>
</beans>
I also tried both of the following:
brokerURL="vm://localhost?brokerConfig=xbean:classpath:activemq.xml"
(And putting it in WEB-INF)
brokerURL="vm://localhost?brokerConfig=xbean:classpath:WEB-INF/activemq.xml"
It never uses MySQL.
A couple ways..
Crank up the logging of org.apache.activemq to DEBUG or TRACE
Add an additional entry on an open port 61618.. confirm it is listening using netstat.
Also, you can connect up to JMX of the running JVM process and see the org.apache.activemq JMX beans present.
A couple references:
ActiveMQ+Camel+Tomcat
ActiveMQ xbean uri
(Partially from the help of #Matt_Pavlovich)
You have to use the classpath: key under the xbeans AND it has to be in a directory that can be found on the WAR classpath (e.g. META-INF):
brokerURL="vm://localhost?brokerConfig=xbean:classpath:META-INF/activemq.xml"
While deploying a project with jndi resource facing this error.
javax.naming.NameNotFoundException: Name [jdbc/skynetdb] is not bound in this Context. Unable to find [jdbc]
Here "jdbc/skynetdb" is the name of the jndi resource defined in context.xml file as:
<Resource auth="Container" driverClassName="com.mysql.jdbc.Driver"
global="jdbc/skynetdb" maxActive="100" maxIdle="30" maxWait="10000"
name="jdbc/skynetdb" password="" type="javax.sql.DataSource"
url="jdbc:mysql://localhost:3306/skynetdb" username="root" />
And dataSource bean in spring.xml file is declared as:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/skynetdb" />
</bean>
Problem solved:
I just modified the dataSource bean in spring.xml file as shown:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/skynetdb" />
</bean>
Set this property 'resourceRef' for class JndiObjectFactoryBean
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/skynetdb" />
<property name="resourceRef" value="true" />
</bean>
Hope this will work
Thanks
Karthick
I want to maintain connection pooling into my java/spring application. For this i used spring configuration file. Which looks like this
<bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${db.driver}"/>
<property name="url" value="${db.jdbcurl}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
<property name="initialSize" value="3"/> T
<property name="maxActive" value="100"/>
</bean>
This application war is hosted into tomcat. When i saw tomcat context.xml file which is set by some network team. Context.xml file also contain some configuration regarding the connection pooling.It looks like this
<Context>
<Resource name="jdbc/test"
auth="Container"
type="javax.sql.DataSource"
username="naveen"
password="12345"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql:localhost:3306/cyl"
maxActive="15"
maxIdle="3"/>
</Context>
Now i have two question to asked
1) Which connection pool configuration will apply when application runs.
2) If we have multiple war a.war(with connection pool config), b.war(with out CPC), c.war(without CPC) then, will tomcat connection pool setting will apply to all application.
3) what can be max value for maxActive attribute.
Thanks in advance
Currently we are loading our JDBC source values from properties file as per following:
<context:property-placeholder location="classpath:master.properties" ignore-unresolvable="true" />
<bean id="mainDataSource" class="com.jolbox.bonecp.BoneCPDataSource"
destroy-method="close">
<property name="driverClass" value="${database.driver}" />
<property name="jdbcUrl" value="${database.url}" />
<property name="username" value="${database.user}" />
<property name="password" value="${database.password}" />
<property name="idleConnectionTestPeriod" value="60" />
<property name="idleMaxAge" value="240" />
<property name="maxConnectionsPerPartition" value="2" />
<property name="minConnectionsPerPartition" value="2" />
<property name="partitionCount" value="3" />
<property name="acquireIncrement" value="10" />
<property name="statementsCacheSize" value="50" />
<property name="releaseHelperThreads" value="3" />
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy"
scope="singleton">
<property name="targetDataSource">
<ref local="mainDataSource" />
</property>
</bean>
This seg. works fine with classpath based app.properties file and get rid of app.properties.
We would like to load this values from context.xml (either placed in META-INF or $CATALINA_HOME/conf/context.xml). It will help us load proper values at prod/staging servers.
Will appreciate any help or alternate method/suggestions. (If similar question is already answered, please share the link)
Thanks!
As Alan Hay mentioned you could externalize the datasource configuration into Tomcat's own context.xml and then have Spring do a JNDI lookup to retrieve it. This is an approach that I've commonly used on some of the projects I've worked on.
The pieces you need to put in place to achieve would be:
1. Add the datasource configuration to $CATALINA_HOME/conf/context.xml
<GlobalNamingResources>
<Resource type="javax.sql.DataSource"
name="dsName"
factory="com.jolbox.bonecp.BoneCPDataSource"
driverClassName="your.driver.classname"
jdbcUrl="your:driver:url"
username="username"
password="password"
idleMaxAge="240"
idleConnectionTestPeriod="60"
partitionCount="3"
acquireIncrement="10"
maxConnectionsPerPartition="2"
minConnectionsPerPartition="2"
statementsCacheSize="50"
releaseHelperThreads="3" />
</GlobalNamingResources>
2. Add a resource link in the application's META-INF/context.xml
<Context path="/YourApp">
<ResourceLink description="Datasource for YourApp"
global="jdbc/dsName"
name="jdbc/dsName"
type="javax.sql.DataSource" />
</Context>
3. Modify the Spring config to lookup the datasource in JNDI
<beans xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/jee classpath:/org/springframework/ejb/config/spring-jee-3.0.xsd">
<jee:jndi-lookup id="dataSource"
jndi-name="java:comp/env/jdbc/dsName" />
4. Move the driver and datasource jars
Since the datasource configuration is now container managed, you should place the database driver and datasource jars into $CATALINA_HOME/lib so they are available to Tomcat when it creates the datasource. These jars should no longer need to reside in the WEB-INF/lib of your application.
The way I do it, I have default properties file in my classpath, and I have one properties file that I use to override those default (development) properties:
in my spring file:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="true"/>
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
<value>classpath:camel.properties</value>
<value>classpath:email.properties</value>
<value>${external_config}</value>
</list>
</property>
</bean>
In development, I use the properties file in the classpath.
On the different envionment, staging, integration, production we start the application with the following parameter:
-Dexternal_config=file:c:/staging.properties
That way I have the same build for all environments and can choose the location of my overriding properties file.
So, ${external_config} is a place holder for a configuration file that depends on the environment.
Spring looks for an environment variable named external_config, that variable should point to a configuration file. If the file is not found, Spring ignores it with ignoreResourceNotFound = true;
Spring 3.1 introduced support for environment specific profiles. Define some profiles, associate them with some properties files e.g. test.properties, live.properties and set an environment variable on server start -Dspring.profiles.active=Test. Clean and simple.
http://spring.io/blog/2011/02/11/spring-framework-3-1-m1-released/
Other option as hinted at above is to shift to a container managed Connection Pool looked up via JNDI i.e define a JNDI datasource named xyz the same on each server and then:
I need to have a development and production settings for our spring project. I understand that you can use profiles for spring but that is not something that we can do.
What I want to do is place on the development environment a test-application.properties file and on production a prod-application.properties file. In the tomcat context definition we sent the following:
<Context>
<context-param>
<param-name>properties_location</param-name>
<param-value>file:C:\Users\Bill\test-application.properties</param-value>
</context-param>
</Context>
And we can have the value changed for the production servers. In the spring config we have something like this:
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="locations">
<list>
<value>${properties_location}</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="false" />
</bean>
But we keep getting errors like:
org.springframework.beans.factory.BeanInitializationException: Could
not load properties; nested exception is
java.io.FileNotFoundException: Could not open ServletContext resource
[/${properties_location}]
Any ideas on how to solve?
One feature of PropertyPlaceholder is that you can define multiple resource locations.
So for example you can define your-production-config.properties along with file:C:/Users/${user.name}/test-application.properties
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:your-production-config.properties</value>
<value>file:C:/Users/${user.name}/test-application.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="ignoreResourceNotFound" value="true"/>
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
</bean>
for production you need to place prod configuration into classpath somewhere(really not important where exactly, just classpath) - for local env you can use convension like this file:C:/Users/${user.name}/test-application.properties
<context:property-placeholder location="file:${catalina.home}/conf/myFirst.properties" ignore-unresolvable="true" />
<context:property-placeholder location="classpath:second.properties" ignore-unresolvable="true" />
I do it like above. The catalina.home variable allows the properties file to be lcoated in the tomcat home conf directory.
I ended up solving it by not using context params. Instead we have defined
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:application.properties</value>
<value>file:C:\Users\Bill\prod-application.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="ignoreResourceNotFound" value="true"/>
</bean>
This way tries to load both files. On test servers we do not have the prod file so it is not loaded. On prod server the prod-application.properties file exists and overrides the test which is in the classpath. Cumbersome but works!
Personally, try to avoid specify locations. I think best thing for you is to use JNDI to achieve this.
In tomcat/conf/server.xml
<Resource name="jdbc/prod" auth="Container"
type="javax.sql.DataSource" driverClassName="${database.driverClassName}"
url="${database.url}"
username="${database.username}" password="${database.password}"
maxActive="20" maxIdle="10"
maxWait="-1"/>
and In tomcat catalina.properties (If using Oracle XE otherwise change it accordingly):
database.driverClassName=oracle.jdbc.driver.OracleDriver
database.url=jdbc:oracle:thin:#//localhost:1521/XE
database.username=user
database.password=password
In your application create properties file in your classpath named jdbc.properties and put followings (If using Oracle XE otherwise change it accordingly)
jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:user/password#//localhost:1521/XE
then In Spring applicationContext.xml
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/prod" />
<property name="defaultObject" ref="dataSourceFallback" />
</bean>
<bean id="dataSourceFallback" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="poolPreparedStatements">
<value>true</value>
</property>
<property name="maxActive">
<value>4</value>
</property>
<property name="maxIdle">
<value>1</value>
</property>
</bean>
use :
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="locations">
<list>
<value>C:/Users/Bill/test-application.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="false" />
</bean>
Remove below code from web.xml
<Context>
<context-param>
<param-name>properties_location</param-name>
<param-value>file:C:\Users\Bill\test-application.properties</param-value>
</context-param>
</Context>
if you are using Tcserver and server.xml to configure Resources like database,queues etc you can using the com.springsource.tcserver.properties.SystemProperties
Delcare this listener in server.xml like below
<Listener className="com.springsource.tcserver.properties.SystemProperties"
file.1="${catalina.base}/conf/password.properties"
file.2="${catalina.base}/conf/server.properties"
immutable="false"
trigger="now"/>
Now you can externalize the properties to the two files password.properties and server.properties.