Tomcat 8, axis2 webservices aar, spring jndi not bound in context - windows

I have been working on an issue where JNDI name is not found in the context an axis2 webservice is running. This issue is only in Tomcat 8 when I use spring.
Some details: (I will provide the elements that are relevant)
1. services.xml
<service name="ScoreService" class="com.bpl.ws.service.ScoreServiceInitializer">
<description>Simple test service</description>
<parameter name="ServiceObjectSupplier" locked="false">org.apache.axis2.extensions.spring.receivers.SpringAppContextAwareObjectSupplier</parameter>
<parameter name="SpringBeanName" locked="false">scoreService</parameter>
2. server.xml:
<Host name="localhost" appBase="webapps" xmlBase="C:\Applications\apache-tomcat-8.0.30-windows-x64\context"
unpackWARs="true" autoDeploy="true">
Context.xml
<JarResources className="org.apache.catalina.webresources.DirResourceSet"
base="C:\Applications\apache-tomcat-8.0.30-windows-x64\commonLib" webAppMount="/WEB-INF/lib"/>
4.JNDI resource in the context file:
<Resource name="jdbc/ADS" auth="Container"
factory="com.bpl.ws.EncryptedJdbcDataSourceFactory"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:#xxxxxxx.com:3203/xxxx"
username="xxxxx"
password="xxxx"
initialSize="10"
logAbandoned="false"
maxActive="20"
maxIdle="10"
maxWait="10000"
removeAbandoned="true"
removeAbandonedTimeout="120"
jdbcInterceptors="QueryTimeoutInterceptor(queryTimeout=10)"
testOnBorrow="true"
validationInterval="30000"
validationQuery="Select 1 from dual"/>
As shown in services.xml file listing, I am using an initializer class and the code to load the spring context looks like this:
4.ScoreSerivceInitializer
public void startUp(ConfigurationContext ignore, AxisService service) {
System.out.println("SCORESERVICE:: Starting up..");
DataSource ds;
ClassLoader cloader = service.getClassLoader();
Thread.currentThread().setContextClassLoader(cloader);
System.out.println("SCORESERVICE:: spring context starting up");
spContext = new ClassPathXmlApplicationContext(new String[] {"DST-Context.xml"},false);
spContext.setClassLoader(cloader);
try {
spContext.refresh();
spring context.xml (DST-Context.xml)
The DST-Context.xml entry looks like this:
<bean id="applicationContext"
class="org.apache.axis2.extensions.spring.receivers.ApplicationContextHolder" />
<bean id="datasource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jdbc/ADS</value>
</property>
</bean>
Tomcat log:
[WARN] Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'datasource' defined in class path resource [DST-Context.xml]: Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: Name [java:comp/env/jdbc/ADS] is not bound in this Context. Unable to find [java:comp].org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'datasource' defined in class path resource [DST-Context.xml]: Invocation of init method failed; nested exception is javax.naming.NameNotFoundException:
Name [java:comp/env/jdbc/ADS] is not bound in this Context. Unable to find [java:comp].
Without changing anything in the configuration, if I changed the ScoreServiceInitializer to do this:
initCtx = new InitialContext();
envCtx = (Context) initCtx.lookup("java:comp/env");
ds = (DataSource)
envCtx.lookup("jdbc/ADS");
Everything works. As you see here I don't use any spring and the jndi datasource is in context.
If I deploy the code with spring config in Tomcat 7, it works fine.
The spring context seems to be the issue but have been looking at it for a while and cant seem to figure out why Tomcat 8 has a different behavior compared to Tomcat 7. I know that Tomcat8 has changed some behavior in terms of how the Resources are configured and the dbcp is now dbcp2 and I have updated config files accordingly.
Any help is greatly appreciated. Please let me know if any other info is required.

#bplso I had the same issue when I upgrade tomcat7 to tomcat8.5 on a axis2 project, try the steps given in image. It may be solve your issue.
!
Step 1: Specify the connection resource in server.xml inside <GlobalNamingResources> like
<Resource name="jdbc/name"
global="jdbc/name"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
auth="Container"
type="javax.sql.DataSource"
username="xxx"
password="YYY"
driverClassName="net.sourceforge.jtds.jdbc.Driver"
url="jdbc:jtds:sqlserver://host:port/dbname"
maxTotal="10"
maxIdle="10"
maxWaitMillis="10000" />
Step 2: Specify the resource reference in web.xml inside the <web-app> like
<resource-ref>
<description> This is a reference to the global Resource for SQL database connetion. </description>
<res-ref-name>jdbc/name</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
Step 3: Create a context.xml file and paste it in your project/META-INF/ path as below
<?xml version=.1.0 encoding="UTF-8.?>
<Context>
<ResourceLink name="jdbc/name" global="jdbc/name" type="javax.sgl.DataSource"
</Context>

Related

Grails database configuration

I'm trying to make some changes to the database configuration for a Grails application. Grails version is 2.5.3.
The goal is to remove hard coded dependencies to MySql to be able to use the application with other database providers.
I am also trying to run locally with environment set to prod and with a local MySql database. (To be able to test my changes without deploying, since the "dev" environment uses the H2 database which is set up quite different.) So I'm starting with mvn grails:run-app -Dgrails.env=prod.
I'm not very experienced with Grails and a lot of things seems to happen "magically" which makes troubleshooting a little difficult.
Some configuration files that seems to be involved are:
context.xml. As I understand it this is a tomcat configuration file on the server (outside the application). There is also a myapp/resources/tomcat-conf/context.xml which I believe is used when I'm running locally. context.xml contains a database configuration like this:
<Context>
...
<Resource name="jdbc/TP" auth="Container" type="javax.sql.DataSource"
maxActive="10" maxIdle="5" maxWait="10000" username="xxx" password="xxx"
driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://xxx:3306/xxx?autoReconnect=true" validationQuery="select 1"
/>
...
</Context>
Then there is a myapp/src/main/resources/myapp-PROD.xml
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false" />
<property name="generateDdl" value="false" />
<property name="database" value="MYSQL" />
</bean>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/TP"/>
<property name="resourceRef" value="true" />
</bean>
I would like to get rid of the hardcoded "MYSQL" here and preferable be able to get that from context.xml (or a properties file on the server).
myapp-PROD.xml also imports myapp-config.xml which contains:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
Then there is some configuration in myapp/grails-app/conf/DataSource.groovy:
(Including some outcommented configuration)
environments {
...
production {
dataSource {
// driverClassName = "com.mysql.jdbc.Driver"
// username = "xxx"
// password = "xxx"
// url = "jdbc:mysql://xxx:3306/xxx"
jndiName = "java:comp/env/jdbc/TP"
}
}
}
And there is also myapp/grails-app/conf/BootStrap.groovy which does some H2 configuration for "dev" and "test" but no database configuration for "prod".
So I have tried to specify my local MySql database in context.xml. It does not work well. In myapp/target/tomcat/logs/myapp.log I can see this:
*2022-05-23 13:40:01,669 [localhost-startStop-1] DEBUG spring.OptimizedAutowireCapableBeanFactory - Invoking afterPropertiesSet() on bean with name 'dialectDetector'
2022-05-23 13:40:05,703 [localhost-startStop-1] WARN spring.GrailsWebApplicationContext - Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManagerPostProcessor': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Cannot resolve reference to bean 'hibernateProperties' while setting bean property 'hibernateProperties'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'hibernateProperties': Cannot resolve reference to bean 'dialectDetector' while setting bean property 'properties' with key [hibernate.dialect]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dialectDetector': Invocation of init method failed; nested exception is org.springframework.jdbc.support.MetaDataAccessException: Error while extracting DatabaseMetaData; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (**Could not create connection to database server. Attempted reconnect 3 times. Giving up.**)*
I don't see any connection attempts in my database logs, so obviously it is not trying to connect to the database i specified in context.xml.
I also tried to specify the database in DataSource.groovy, but that didn't work either.
So:
What do I need to do to run locally with my local MySql database?
Is there any additional helpful logs I can enable?
How do I get rid of "MYSQL" in myapp-PROD.xml and get dialect from context.xml instead?
What do I need to do to run locally with my local MySql database?
You need to supply a value for the dataSource driver that points to the Mysql driver and you need to supply a JDBC url that the MySql driver recognizes and points to your local MySql.
How do I get rid of "MYSQL" in myapp-PROD.xml and get dialect from
context.xml instead?
The dialect is only 1 piece of the puzzle and probably really isn't the key to the problem. If it really is a requirement to get the dialect from context.xml I don't know how to do it, but a much more common way to deal with the situation is to either use JNDI so you don't have to make any mention of dialects and driver names and user names and passwords in your app. Another option is to put the database config in an external config file that is loaded by the app at startup time.

Error creating bean defined in ApplicationContext.xml

I am porting Spring( v.4.3.2) application from Tomcat7 to Tomcat9. I am running Tomcat as a service on Windows box. in my ApplicationContext.xml I have several Beans profiles defined and I also have bean definitions outside of profiles :
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="utilsDS" />
</bean>
.............
....
<bean id="utilsDS" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver" />
</bean>
....
</beans>
When I am starting Tomcat I am passing a JVM option :
-Dspring.profiles.active='UAT'
Tomcat 7 starts my application perfectly fine and I am able to run it. However with Tomcat 9 I am getting an error
org.apache.catalina.core.StandardContext.listenerStart Exception sending context initialized event to listener instance of class [org.springframework.web.context.ContextLoaderListener]
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'transactionManager' defined in ServletContext resource [/WEB-INF/config/applicationContext.xml]:
Cannot resolve reference to bean 'utilsDS' while setting bean property 'dataSource';
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No bean named 'utilsDS' is defined
"applicationContext.xml" are identical on Tomcat 7 and 9 since I used the same WAR to deploy an application. I am not sure what I'm missing.
It seems to me it's something in configuration of Tomcat9 that would resolve the reference. I am not sure what it is.
I added context-param to an application "web.xml" and it works :
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>dev</param-value>
</context-param>
still not sure why passing JVM option :
-Dspring.profiles.active=dev
didn't work

Defining a datasource resource in tomcat context.xml

I'm using Spring batch and spring batch admin and i write in applicationContext this code, defining a bean called dataSource:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" ... />
Now, i would change this code, defining my "dataSource" in the context.xml file of Tomcat and then load it.
I read that this is possible defining a Resource like this:
<Resource auth="Container" driverClassName="oracle.jdbc.driver.OracleDriver"
maxActive="100" maxIdle="30" maxWait="10000" name="jdbc/myDatabase"
password="myPass" type="javax.sql.DataSource"
url="jdbc:oracle:thin:#host.com:1521/abc" username="myUser" />
and then loading it in my applicationContext.xml using this:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/myDatabase" />
But with this i have a problem. It is possible to define a resource for my dataSource so that it is of class org.apache.commons.dbcp.BasicDataSource and not javax.sql.DataSource?
Any help?
Thank you

JNDI DataSource: migrating from Tomcat to jBoss/Wildfly

I have a web application that uses Tomcat 7, Spring MVC 4.0, and JPA (Hibernate implementation). I am migrating this application to jBoss/Wildfly application server.
Currently, the DataSource is injected in the application with JNDI in a Spring configuration file:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/MY_DB" expected-type="javax.sql.DataSource" />
The data source itself is defined in $CATALINA_HOME/conf/context.xml in the following way:
<Context>
<Resource name="jdbc/MY_DB"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/MY_DB?useUnicode=yes&characterEncoding=UTF-8"
username="user1"
password=""
validationQuery="select 1"
removeAbandoned="true"
removeAbandonedTimeout="120"
maxWait="60"
maxActive="20"
maxIdle="10" />
</Context>
How can I define this JNDI DataSource in JBoss/Wildfly?
First, you must make the JDBC driver available to the application server; then you can configure the data source itself.
See more details in Data Source Configuration in AS 7 and DataSource configuration

Spring DataSource configuration using JNDI

I am having trouble configuring the dataSource bean using JNDI in the Spring applicationContext.xml file.
This is how my applicationContext.xml entry looks like:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/myApp" expected-type="javax.sql.DataSource"/>
I have made an entry in web.xml:
<resource-env-ref>
<resource-env-ref-name>jdbc/myApp</resource-env-ref-name>
<resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type>
<resource-env-ref>
Context.xml file in Tomcat:
<Resource
auth="Container"
factory="bitronix.tm.resource.ResourceObjectFactory"
name="jdbc/myApp" type="javax.sql.DataSource"
uniqueName="jdbc/myApp" />
With these configuration I keep getting this error on Tomcat console:
Caused by: javax.naming.NameNotFoundException: Name [jdbc/myApp] is not bound in this Context. Unable to find [jdbc].
at org.apache.naming.NamingContext.lookup(NamingContext.java:819)
at org.apache.naming.NamingContext.lookup(NamingContext.java:167)
at org.apache.naming.SelectorContext.lookup(SelectorContext.java:156)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:155)
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:179)
at org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:104)
at org.springframework.jndi.JndiObjectLocator.lookup(JndiObjectLocator.java:106)
at org.springframework.jndi.JndiObjectFactoryBean.lookupWithFallback(JndiObjectFactoryBean.java:231)
at org.springframework.jndi.JndiObjectFactoryBean.afterPropertiesSet(JndiObjectFactoryBean.java:217)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549)
Please help me resolve this issue. It appears to me that the bitronix transaction factory in Context.xml is causing the issue.
You need to use a different jndi name, because in Tomcat all configured entries and resources are placed in the java:comp/env portion of the JNDI namespace and you need to specify that, as well:
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/myApp" expected-type="javax.sql.DataSource"/>

Resources