I am using JEE5 with Postgresql, When I try to persist the object the output says
Could not find datasource: java:jdbc/postgres
javax.naming.NameNotFoundException: the name jdbc/postgres is not
asociated with this context
In context.xml (Tomcat7) I have
<Context>
<Resource name="jdbc/postgres" auth="Container"
type="javax.sql.DataSource" driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://127.0.0.1:5433/peopledb"
username="postgres" password="password" maxActive="20" maxIdle="10"
maxWait="-1"/>
</Context>
In persistence.xml I have:
<persistence-unit name="People">
<jta-data-source>java:jdbc/postgres</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="true" />
</properties>
</persistence-unit>
In my persistence bean I have
#Stateless
public class PeopleDAOImpl implements PeopleDAO {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("People");
#Override
public void persistPeople(People pep) {
EntityManager em = emf.createEntityManager();
em.persist(pep);
}
}
Tomcat names the context resources differently than Glassfish. You defined the name in context.xml as jdbc/postgres, but in the persistence.xml you have to use java:comp/env/jdbc/postgres.
A late reply, but maybe still useful for others:
JTA can be used in Tomcat with componentized implementations like Atomikos (https://www.atomikos.com).
Cheers
PS: if you want help in setting things up you may want to consider a free trial of Atomikos - which includes Tomcat support / setup.
Related
How does spring know which connection pool to use?
As is known ,you tell the spring framework a persistence-unit name,and annotate the entity manager with #PersistenceContext,and with Persistence.xml configured.Spring does every thing for you.
I am very confused about the spring annotation "#PersitenceContext" above the entityManager field.
My persistence.xml is as below :
<persistence-unit name="hibernate.recommendation_report.jpa">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver" />
<property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:#192.168.113.226:11521:BOSS" />
<property name="javax.persistence.jdbc.user" value="xxxx" />
<property name="javax.persistence.jdbc.password" value="xxxx" />
</properties>
</persistence-unit>
My tomcat server and my webapp work well when and after for a short peoriod of time after the starting up of tomcat server.But hours later,the server reports a sqlexception "Connection already closed".
Is this the problem of misusing db connection pool? How do the spring framework choose a c3p0 or DBCP ? How would I specify the connection pool? Or is the tomcat uses the default DBCP as the connection pool?
U can make your tomcat server or other app server provide the JNDI datasource. So that, the your server container's self-contained connection pool can take good care of your the database connection/session.
Tomcat in your case, you specify the JNDI datasource in the $TOMCAT_HOME/conf/context.xml or server.xml:
<Resource name="jdbc/sample" auth="Container"
type="com.mchange.v2.c3p0.ComboPooledDataSource"
username=...
password=...
url=...
driverClassName=...
/>
the type attribute tells the tomcat which connection pool to use.
By default tomcat6 uses DBCP with type of "java.sql.DataSource".
Make sure to use the JNDI reference in your persistence.xml:
<persistence version="2.1" ....>
<persistence-unit name="hibernate.recommendation_report.jpa">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<non-jta-data-source>java:comp/env/jdbc/sample</non-jta-data-source>
</persistence-unit>
</persistence>
Or use spring xml to config the datasource bean to inject into the your entityManagerFactory.Please refer to here.
<jee:jndi-lookup id="dataSource" jndi-name="java:sample"/>
See other JNDI resource attributes available for DBCP.
Note: the "java:comp/env/" prefix in persistence.xml data-source is very import.Without it, Spring will not look for the pool provided by your application server to fetch datasource but just use the attribute to construct a simple datasource.
Note: tomcat8 itself provides a even better pool.If you upgrade to tomcat8.
I was wondering if anyone has any code examples for setting up a connection pool in Tomcat (7 or later) using MyBatis as the ORM.
I presume I need to add a resource to my context.xml file in my Tomcat conf folder and then link that to MyBatis. I've had a look and any tutorials I have found seem to be Spring specific. Does anyone have a simple tutorial or can they outline the steps required to get this up and running?
There is this old entry in the iBatis FAQ that should still be applicable to myBatis: How do I use a JNDI DataSource with iBATIS in Tomcat?.
You can google for the details to configure a datasource in your Tomcat version, then configure MyBatis as well (it's different than the iBatis configuration):
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="JNDI">
<property name="data_source" value="java:comp/env/jdbc/yourDatasourceName"/>
</dataSource>
</environment>
There are a number of ways you can do this. I am assuming that you mean to implement Tomcat (as opposed to Spring) managed connection pooling. I have tested on MySQl/Spring 4/Mybatis-spring 1.1 stack.
Figure out the connection pooling mechanism you want to implement (C3P0/DBCP etc).
If you want to use your database as a JNDI data source, then you have to declare it as a resource in Tomcat settings. There are a number of ways to do this. You can follow this well written guide Tomcat JNDI connection pooling. I generally add the following entry in context.xml located in the META-INF directory of my app:
<Context>
<Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource" maxTotal="100" maxIdle="30" maxWaitMillis="10000" username="javauser" password="javadude" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/javatest"/>
</Context>
This file is used by Tomcat to invoke its own default connection pool, which in this case would be DBCP 2. You can tweak its settings by adding more parameters (like removeAbandonedOnBorrow=true) in the Resource element above. You should put the driver jar (eg MySQL Connector Jar) of your database in Tomcat's lib folder.
After this, depending on your Mybatis implementation (XML or bean based), you can inject this data source into Mybatis. If you are doing it the bean way, you can do it like this:
<bean id="dbDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/TestDB"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dbDataSource" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dbDataSource" />
<property name="typeAliasesPackage" value="com.example.model"/>
<property name="mapperLocations" value="classpath*:*.xml" />
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.example.dao" />
</bean>
MapperScannerConfigurer is necessary because it searches the directories given to it to find mapper xml files. You can also use the old way of defining a mybatis-config.xml file by injecting the file's location in the sqlSessionFactory bean in its configLocation property.
I am learning J2EE recently.
I use IntelliJ, and my web server is Tomcat. I want to add OpenJPA to my project, but I meet some problems.
I have two entities: BooksEntity and SourcesEntity.
When I called createEntityManager() in the Servlet, it gave me a NullPointerException.
It seems that I missed something, but I don't know why.
Here is the exception information:
java.lang.NullPointerException
controller.TestServlet.doGet(TestServlet.java:28)
javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
This is my TestServlet.java file:
#WebServlet(name = "TestServlet", urlPatterns = {"/books"})
public class TestServlet extends HttpServlet {
#PersistenceUnit (unitName = "booksPU")
private EntityManagerFactory emf;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
EntityManager em = emf.createEntityManager();
Query query = em.createNamedQuery("Books.findAll");
request.setAttribute("books", (List<BooksEntity>) query.getResultList());
request.getRequestDispatcher("index.jsp").forward(request, response);
}
}
The exception was thrown in this line: EntityManager em = emf.createEntityManager();
This is my context.xml file:
<Context>
<Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
username="root" password="******" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/FIRST_TEST"/>
</Context>
My persistence.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="booksPU">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<class>model.BooksEntity</class>
<class>model.SourcesEntity</class>
<properties>
<property name="openjpa.ConnectionURL" value="jdbc:mysql://localhost:3306/FIRST_TEST"/>
<property name="openjpa.ConnectionDriverName" value="com.mysql.jdbc.Driver"/>
<property name="openjpa.ConnectionUserName" value="root"/>
<property name="openjpa.ConnectionPassword" value="******"/>
</properties>
</persistence-unit>
</persistence>
========2014.06.06========
My directory structure:
========2014.06.07========
This is probably just a typo in your code. The annotation should be #PersistenceContext, not #PersistentUnit. This is why emf remains null.
Make sure that when you package your war file the persistence.xml is located in WEB-INF/classes/META-INF folder.
I have been learning about how to set up Tomcat's connection pool through this website. So I made a context.xml file and put it in the directory META-INF. This is what I have right now.
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource name="jdbc/gmustudent" auth="Container"
type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver"
username="root" password="root"
url="jdbc:mysql://localhost:3306/official"
maxActive="100" maxIdle="10" minIdle="5" initialSize="5" maxWait="10000" />
</Context>
However I would like to specify the class name of the factory. But everytime I add this attribute
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
I get a huge pile of errors in my console. Here are some of them in no particular order.
WARNING: Failed to register in JMX: javax.naming.NamingException: com.mysql.jdbc.Driver
WARNING: Unexpected exception resolving reference java.sql.SQLException: com.mysql.jdbc.Driver
WARNING: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.jee.server:gmustudent' did not find a matching property.
So when I do not specify a factory the site works just fine. But when I do errors are thrown and nothing works. I did some research on stack overflow and found this post. Because of this I changed my tomcat version from 7.0.11 to the most recent but am still getting the error. So then I thought maybe it is some kind of clash with my factory in my server.xml file but I am not nearly experienced to make that call. But here is the resource in my server.xml file
<Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
So is this clashing with the factory in my context.xml file? Or am I totally wrong here? In a nut shell I would like to find out how to specify a factory in my context.xml file without getting a huge error. Thank you for reading.
You can actually manage the entire connection in your web app using Spring if you want. Here is an example using PostgreSQL:
<?xml version="1.0" encoding="windows-1252"?>
<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="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value="jdbc:postgresql://localhost/mydb"/>
<property name="username" value="postgres"/>
<property name="password" value="postgres"/>
</bean>
</beans>
You can just put that in WEB-INF/classes and load it using:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/mycontext.xml");
I wouldn't even bother with having Tomcat manage it at this point.
It is said that in the Spring javadoc article about DriverManagerDataSource class, that this class is very simple and that it is recommended
to use a JNDI DataSource provided by the container. Such a DataSource can be exposed as a DataSource bean in a Spring ApplicationContext via JndiObjectFactoryBean
The question is: how do I accomplish this?
For example, if I wish to have DataSource bean to access my custom MySQL database, what would I require then? What should I write in the context configuration, etc?
If using Spring's XML schema based configuration, setup in the Spring context like this:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd">
...
<jee:jndi-lookup id="dbDataSource"
jndi-name="jdbc/DatabaseName"
expected-type="javax.sql.DataSource" />
Alternatively, setup using simple bean configuration like this:
<bean id="DatabaseName" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/DatabaseName"/>
</bean>
You can declare the JNDI resource in tomcat's server.xml using something like this:
<GlobalNamingResources>
<Resource name="jdbc/DatabaseName"
auth="Container"
type="javax.sql.DataSource"
username="dbUser"
password="dbPassword"
url="jdbc:postgresql://localhost/dbname"
driverClassName="org.postgresql.Driver"
initialSize="20"
maxWaitMillis="15000"
maxTotal="75"
maxIdle="20"
maxAge="7200000"
testOnBorrow="true"
validationQuery="select 1"
/>
</GlobalNamingResources>
And reference the JNDI resource from Tomcat's web context.xml like this:
<ResourceLink name="jdbc/DatabaseName"
global="jdbc/DatabaseName"
type="javax.sql.DataSource"/>
Reference documentation:
Tomcat 8 JNDI Datasource HOW-TO
Tomcat 8 Context Resource Links Reference
Spring 4 JEE JNDI Lookup XML Schema Reference
Spring 4 JndiObjectFactoryBean Javadoc
Edit: This answer has been updated for Tomcat 8 and Spring 4. There have been a few property name changes for Tomcat's default datasource resource pool setup.
With Spring's JavaConfig mechanism, you can do it like so:
#Configuration
public class MainConfig {
...
#Bean
DataSource dataSource() {
DataSource dataSource = null;
JndiTemplate jndi = new JndiTemplate();
try {
dataSource = jndi.lookup("java:comp/env/jdbc/yourname", DataSource.class);
} catch (NamingException e) {
logger.error("NamingException for java:comp/env/jdbc/yourname", e);
}
return dataSource;
}
}
Assuming you have a "sampleDS" datasource definition inside your tomcat configuration, you can add following lines to your applicationContext.xml to access the datasource using JNDI.
<jee:jndi-lookup expected-type="javax.sql.DataSource" id="springBeanIdForSampleDS" jndi-name="sampleDS"/>
You have to define the namespace and schema location for jee prefix using:
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd"
Documentation: C.2.3.1 <jee:jndi-lookup/> (simple)
Example:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/MyDataSource"/>
You just need to find out what JNDI name your appserver has bound the datasource to. This is entirely server-specific, consult the docs on your server to find out how.
Remember to declare the jee namespace at the top of your beans file, as described in C.2.3 The jee schema.
Another feature:
instead of of server.xml, you can add "Resource" tag in
your_application/META-INF/Context.xml
(according to tomcat docs)
like this:
<Context>
<Resource name="jdbc/DatabaseName" auth="Container" type="javax.sql.DataSource"
username="dbUsername" password="dbPasswd"
url="jdbc:postgresql://localhost/dbname"
driverClassName="org.postgresql.Driver"
initialSize="5" maxWait="5000"
maxActive="120" maxIdle="5"
validationQuery="select 1"
poolPreparedStatements="true"/>
</Context>
According to Apache Tomcat 7 JNDI Datasource HOW-TO page there must be a resource configuration in web.xml:
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/TestDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
That works for me
In your spring class, You can inject a bean annotated like as
#Autowired
#Qualifier("dbDataSource")
private DataSource dataSource;
and You add this in your context.xml
<beans:bean id="dbDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<beans:property name="jndiName" value="java:comp/env/jdbc/MyLocalDB"/>
</beans:bean>
You can declare the JNDI resource in tomcat's server.xml using
<Resource name="jdbc/TestDB"
global="jdbc/TestDB"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/TestDB"
username="pankaj"
password="pankaj123"
maxActive="100"
maxIdle="20"
minIdle="5"
maxWait="10000"/>
back to context.xml de spring add this
<ResourceLink name="jdbc/MyLocalDB"
global="jdbc/TestDB"
auth="Container"
type="javax.sql.DataSource" />
if, like this exmple you are injecting connection to database, make sure that MySQL jar is present in the tomcat lib directory, otherwise tomcat will not be able to create the MySQL database connection pool.
I found this solution very helpful in a clean way to remove xml configuration entirely.
Please check this db configuration using JNDI and spring framework.
http://www.unotions.com/design/how-to-create-oracleothersql-db-configuration-using-spring-and-maven/
By this article, it explain how easy to create a db confguration based on database jndi(db/test) configuration. once you are done with configuration then all the db repositories are loaded using this jndi. I did find useful. If #Pierre has issue with this then let me know. It's complete solution to write db configuration.