JNDI spring embedded tomcat : maven multi module project - spring

I still cant get this thing in my head :
this is how my project looks :
--app
--app-core (spring)
--app-model (pojo)
--app-service (jersey) >> final package as war (dependencies (appcore+appmodel))
Now here where should my applicationContext.xml sits ????
Dependencies of Spring goes to only app-core ???? ...
UPDATE
app-core (spring) has applicationContext.xml, Know I would like to use JNDI with embedded tomcat (tomcat-maven-plugin).
Have created context.xml inside webapp/META-INF it looks like :-
<?xml version='1.0' encoding='utf-8'?>
<Context docBase="nweb" path="/nweb" reloadable="true">
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<Resource name="jdbc/TestDS" auth="Container"
type="javax.sql.DataSource"
driverClass="net.sourceforge.jtds.jdbc.Driver"
url="jdbc:sqlserver://localhost:1433;DatabaseName=TestData"
username="sa" password=""/>
</Context>
..
my 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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:/TestDS"></property>
</bean>
</beans>
with the above I get this below error :
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
Caused by: javax.naming.NameNotFoundException: Name TestDSis 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)
at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:87)
at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:152)
at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:178)
at org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:95)
at org.springframework.jndi.JndiObjectLocator.lookup(JndiObjectLocator.java:105)
at
Any suggestions if am missing out anything ?

Typically you would configure a ContextLoaderListener on your web.xml for your root application context:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
This class uses the param value contextConfigLocation -- from which you can explicitly specify where your applicationContext.xml should be:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:META-INF/spring/applicationContext*.xml</param-value>
</context-param>

try
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<contextFile>webapp/META-INF/context.xml</contextFile>
</configuration>
</plugin>

try <property name="jndiName" value="java:comp/env/TestDS"></property>

if you are using embedded tomcat 7 then you should call
tomcat.enableNaming();

You have an application working with JNDI here. I have been using JNDI on a PaaS where they explain how to do the binding between your app and the db. You can have more details on this tutorial.
Basically you need to put this on your datasource.xml file:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/mydb" resource-ref="true"
expected-type="javax.sql.DataSource"/>
Then, on your Tomcat server, you have several possibilities as you can see on the Spring tutorial I put the link. Easiest way is going to $CATALINA_HOME/conf/context.xml and put something like this.
<Resource auth="Container" driverClassName="com.mysql.jdbc.Driver" factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" maxActive="20" maxIdle="10" minIdle="1" name="jdbc/mydb" password="dbUserPassword" testOnBorrow="true" testWhileIdle="true" type="javax.sql.DataSource" url="jdbc:mysql://localhost:3306/dbName" username="dbUserName" validationInterval="5000" validationQuery="select 1"/>

Related

Failed to look up JNDI DataSource In Spring Boot Application

I have done the bellow mentioned configuration for JNDI DataSource connection for Spring Boot Application that uses an external tomcat.
Tomcat's server.xml configuration like
<GlobalNamingResources>
<!-- Editable user database that can also be used by
UserDatabaseRealm to authenticate users
-->
<Resource name="jdbc/MyPostgresDB"
global="jdbc/MyPostgresDB"
auth="Container"
type="javax.sql.DataSource"
driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://localhost:5432/postgres"
username="postgres"
password="postgres"
maxActive="100"
maxIdle="20"
minIdle="5"
maxWait="10000"/>
Context.xml like
<Context>
<!-- Default set of monitored resources -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<ResourceLink name="jdbc/MyPostgresDB"
global="jdbc/MyPostgresDB”
auth="Container"
type="javax.sql.DataSource" />
Defined the application.properties for spring boot in right way like
spring.datasource.jndi-name=java:comp/env/jdbc/MyPostgres
Updated the web.xml like
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<resource-ref>
<description>JNDI LookUp</description>
<res-ref-name>jdbc/MyPostgresDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<!-- <res-sharing-scope>Shareable</res-sharing-scope> -->
</resource-ref>
</web-app>
Still getting the exception like
org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException:
Failed to look up JNDI DataSource with name
'java:comp/env/jdbc/MyPostgres'
(Full Stacktrace not given as every where it is given)
So what is the solution or why I am getting this exception.
Don't come with the idea of embedded tomcat server for spring boot.
Please help me.
Should be
spring.datasource.jndi-name=java:comp/env/jdbc/MyPostgresDB
from what you wrote above in your definitions.
we should add factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" in Resource tag of server.xml and make sure to set JndiDatasource in the class where you extends SpringBootServletInitializer class
For elaborate answer please refer here

Lookup jndi resources WebSphere 8.5, Spring 3.1.3, Hibernate 4.1.10 EJB 3

In my application I need to lookup jndi resources for database connection.
I have an EAR which contain my EJB project with remote and stateless ejb: ABean.jar
Reading Using Spring and Hibernate with WebSphere Application Server I defined
in the application.xml of EAR project:
<module>
<ejb>ABean.jar</ejb>
</module>
<resource-ref>
<res-ref-name>jdbc/b</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
In my spring context:
<jee:jndi-lookup
id="aDataSource"
jndi-name="jdbc/b"
cache="true"
expected-type="javax.sql.DataSource"/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="META-INF/persistence.xml"/>
<property name="dataSource" ref="aDataSource" />
<property name="persistenceUnitName" value="APU"/>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.DB2390Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
Now, if I install application by WebSphere console, it ask to me to assign the jndi resource to jdbc/b (and it is ok), but if I try to call an ejb, a NameNotFoundException is throw because jdbc/b is not found!
Reading better the previous link i see:
For EJB JAR files, the same resource-ref should be declared in each EJB that needs to access the data source.
so I try to define resource references into my ejb-jar.xml
<enterprise-beans>
<session>
<ejb-name>TestServiceBean</ejb-name>
<ejb-class>it.test.TestServiceBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<resource-ref>
<res-ref-name>jdbc/b</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
</resource-ref>
</session>
</enterprise-beans>
I try to install again (I also assign the jndi resource to jdbc/b) and the call to the ejb run successfully, but if I have n ejb, do I need to assign n-times the same jndi resource to the n ejb resource-ref for jdbc/b?
What is wrong with my configuration? Isn't it possible "point" to the same resource-ref from all ejb? Do you have a complete example?
Per the EE 6 spec, references declared in application.xml must be in the java:app (or java:global) namespaces, and it is recommend that they be in the env subcontext, so:
<res-ref-name>java:app/env/jdbc/b</res-ref-name>
This will allow the resource to be visible to all components in the application. Alternatively, you can declare a reference in the java:module context in ejb-jar.xml or via annotation.
Updated answer. Example based on bkail answer. You need to define resource reference in application.xml like this:
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd" version="6">
<display-name>RefTestEAR</display-name>
....
<resource-ref>
<res-ref-name>java:app/env/jdbc/b</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</application>
Then in your application you can access it via:
InitialContext ctx = new InitialContext();
DataSource datasource = (DataSource) ctx.lookup("java:app/env/jdbc/b");
In your case since you are using Spring not InitialContext directly, you will probably need to change the lookup to and also verify if you have datasource reference in persistence.xml (I didn't test that in Spring as I don't have Spring sample at hand):
<jee:jndi-lookup
id="aDataSource"
jndi-name="java:app/env/jdbc/b"
cache="true"
expected-type="javax.sql.DataSource"/>

In Spring/Tomcat, which configuration file do jndi lookups refer to?:

I'm having trouble getting a Spring/Tomcat app to resolve a variable which appears as a property of a JndiFactoryObjectName bean in the application context. Here's the relevant bean entry:
When I try to run it on the server, it comes up with this error:
Caused by: javax.naming.NameNotFoundException: Name search.url is not bound in this Context
This entry in server.xml doesn't seem to help:
There's also an entry in (as seen from Eclipse/STS)
Tomcat v6.0 Server at localhost
Catalina
localhost
ROOT.xml
<Context path="" reloadable="true" docBase="C:/myworkspace32/myAppName/WebContent">
<ResourceLink global="search.url" name="search.url" type="java.lang.String"/>
</Context>
However, this seem to have no impact.
Here are the steps to access JNDI resource from tomcat
Create jndi resource in server.xml
<Resource global="search.url" name="search.url" type="java.lang.String" />
Create the link in context.xml so that its accessible by all the web application.
<ResourceLink name="search.url" global="search.url" auth="Container" type="java.lang.String" />
Use spring bean or jee tag to inject the jndi
<bean id="searchUrl" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/search.url"/>
</bean>
you can avoid specify the environment by using jee contatiner tag as follows
<jee:jndi-lookup id="searchUrl" jndi-name="search.url" expected-type="java.lang.String" />
Follow an example of Tomcat JNDI with Spring
Spring configuration
<?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:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<jee:jndi-lookup id="yourDS" jndi-name="java:comp/env/yourDS"/>
Tomcat configuration (put this in ${catalina.home}\conf\context.xml)
<Resource
name="yourDS"
type="javax.sql.DataSource"
username="****"
password="*****"
driverClassName="com.ibm.db2.jcc.DB2Driver"
url="*******"
maxActive="8"
maxIdle="4"
/>

Configure DBCP inside of Tomcat

I am trying to inject DataSource into Servlet. Finally I've annotated datasource field with #Resource and some DBCP's BasicDataSource was injected there. But it has no configuration. No db url, no driver class, nothing. Naturally I got NullPointerException when trying to getConnection(). What am I doing wrong?
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<servlet>
<servlet-name>testServlet</servlet-name>
<servlet-class>ua.test.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>testServlet</servlet-name>
<url-pattern>/serve</url-pattern>
</servlet-mapping>
<resource-ref>
<res-ref-name>jdbc/MyDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<injection-target>
<injection-target-class>ua.test.TestServlet</injection-target-class>
<injection-target-name>dataSource</injection-target-name>
</injection-target>
</resource-ref>
</web-app>
context.xml
<?xml version='1.0' encoding='utf-8'?>
<Context>
<Resource name="jdbc/MyDB" auth="Container" type="javax.sql.DataSource"
maxActive="10" maxIdle="30" maxWait="10000"
username="tomcat" password="tomcat" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/test"/>
</Context>
Obviously no one gave a sh*t about my sorrow. So I will answer myself.
Tomcat has it's own(probably modified) copy of Apache Commons DBCP under package org.apache.tomcat.jdbc, but also for some stupid reason includes original DBCP under org.apache.commons.dbcp package. What happens when I try to inject Datasource with #Resource annotation is Tomcat instanting Datasource from original package and injecting this instance to my field. To make Tomcat to use his own copy of DBCP I had to modify my context.xml as follows:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource name="jdbc/MyDB"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
auth="Container" type="javax.sql.DataSource"
maxActive="10" maxIdle="30" maxWait="10000"
username="tomcat" password="tomcat"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/test"/>
</Context>
Basicaly I just added this line:
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
Thanks to everyone who knew the reason but ignored this question for so long time :-)

Why do I get an unexpected EntityManagerFactory when using JPA within WebLogic?

I am trying to create a Spring MVC web app (Spring Framework 3.0.5). I am using IntelliJ IDEA 11.1.3 to deploy my app on a WebLogic Server (10.3.4). One of my web pages attempts to store some data in a database using JPA. My persistence.xml specifies:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" 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_2_0.xsd">
<persistence-unit name="LeaveSchedulerJPA" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.engilitycorp.leavetracker.jpa.UserRole</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:#localhost:1521:xe "/>
<property name="javax.persistence.jdbc.user" value="leavescheduler"/>
<property name="javax.persistence.jdbc.password" value="xxx"/>
<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver"/>
</properties>
</persistence-unit>
</persistence>
However, when I look in the debugger, my EntityManagerFactory is shown as an org.apache.openjpa.persistence.EntityManagerFactoryImpl, and when I call createEntityManager, I get an org.apache.openjpa.persistenceArgumentException that states that "A JDBC Driver or DataSource class name must be specified in the ConnectionDriverName property".
It appears to my newbie eye that the persistence.xml may not be getting processed. I've tried putting it in (project)/src/main/resources/META-INF and (project)/src/main/resources/META-INF/spring, with the same unfortunate result.
I am not committed to using Hibernate persistence; however, I do want to use something that implements JPA 2, and I am having a real hard time configuring my environment. For example, I have little idea how openjpa got involved in my app. I suppose it may be the default JPA provider for something (WebLogic?, IntelliJ IDEA?). Any help/suggestions would be much appreciated.
My web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
root-context.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
</beans>
servlet-context.xml:
<?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-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">
<!-- 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.engilitycorp.leavetracker" />
</beans:beans>
WebLogic 10.3.4 is Java EE 5 compliant and is shipped with JPA 1.0 implementations: OpenJPA and TopLink.
According to WebLogic documentation ( http://docs.oracle.com/cd/E17904_01/web.1111/e13720/using_toplink.htm#CIHDJHHI ) it can be used also with JPA 2.0 but only after applying a patch. Simply follow the instructions (patching seems to be quite simple but I didn't test it).
Probably you can also use your own JPA 2.0 provider without patching, as user1654209 wrote in first answer. But JPA 1.0 classes supplied with WebLogic can get in the way, because they are loaded by higher level classloader and have priority over classes packaged in your WAR file. To prevent such behaviour you have two options:
pack your application's WAR within an EAR archive with META-INF/weblogic-application.xml file containing following lines (you must also include standard META-INF/application.xml file):
<?xml version="1.0" encoding="UTF-8"?>
<weblogic-application xmlns="http://xmlns.oracle.com/weblogic/weblogic-application/1.0/weblogic-application.xsd">
<prefer-application-packages>
<package-name>javax.persistence.*</package-name>
</prefer-application-packages>
</weblogic-application>
add WEB-INF/weblogic.xml file to your WAR archive with following lines:
<?xml version='1.0' encoding='UTF-8'?>
<weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/weblogic-web-app">
<container-descriptor>
<prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>
</weblogic-web-app>
You need to configure an entityManagerFactory bean in your context.xml. Heres is an exemple using eclipselink as the JPA provider
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"
id="dataSource">
<property name="driverClassName" value="${database.driverClassName}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
</bean>
<bean
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
id="entityManagerFactory">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean id="jpaAdapter"
class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
</bean>
</property>
</bean>
Just setting the provider isn't enough. You need to set the database connection data, like jdbc url, username and password. Did you set it? You also need to set the jdbc class name, as said, and the jdbc driver needs to be in your classpath.
If you are running this on a container and want to configure the datasource in weblogic, you can just refer to a jndi datasource from your hibernate cfg, but you will need to enter in the weblogic console and create a datasource and a connection pool there.
Look at hibernate docs on how to set the JNDI name in persistence.xml

Resources