Handle Spring data source being temporarily unavailable during Hibernate initialisation - spring

Part of my Spring (4.3.23) / Hibernate (5.0.12) application "A" uses a data source that is exposed be a second application "B" (the data source is an in-memory database). Both A and B are deployed in Tomcat and I don't control start order. Once both A and B have started both behave as expected, however if A starts before B an error is thrown during initialisation when Hibernate tries to query the data source:
org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator - HHH000342: Could not obtain connection to query metadata : Cannot create PoolableConnectionFactory (Connection is broken: "java.net.ConnectException: Connection refused: 127.0.1.1:5521" [90067-199])
Is there any way I can suppress this error, delay this part of initialisation, or tell Hibernate that the data source may not be immediately available?
Here are the relevant parts of my configuration:
<bean id="memDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/memdb" />
</bean>
<bean
id="memSessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="memDataSource" />
<property name="packagesToScan" value="com.company" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
</props>
</property>
</bean>
<bean id="memTransactionManager"class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="memSessionFactory" />
<qualifier value="memTransactions"/>
</bean>
<tx:annotation-driven transaction-manager="memTransactionManager" />

I would wind up scripting the deployment overall. Bring up tomcat with application A in the webapps directory, and periodically ping for successful deployment of application A before copying/moving over application B into the webapps directory for deployment.
This entire solution would likely work best if you used a staging directory to move your war files onto that server, and then let the script clear the webapps directory and move/copy the new war(s) into webapps for fresh deployment.
SideNote: I've found that deployment of applications seems to be in a constant order, but I'm not sure as it is alphabetical, oldest first, or something else.

Related

Update Views With Spring MVC And Thymeleaf Without Redeploy The App

I am using Spring MVC 3.2, Thymeleaf, Thymeleaf dialect with Tomcat and every time that I change a view I don't want redeploy my app. As suggested from others I am setting:
<property name="cacheable" value="false"/>
in the template resolver, but it not working.
Also a full reload (CTRL + F5) has not effect.
Here my full Thymeleaf configuration:
<!-- Thymeleaf template engine -->
<bean id="templateResolver"
class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<property name="prefix" value="/WEB-INF/templates/" />
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML5" />
<property name="cacheable" value="false"/>
</bean>
<bean id="templateEngine"
class="org.thymeleaf.spring3.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
<!-- These lines add the dialect to Thymeleaf -->
<property name="additionalDialects">
<set>
<bean class="nz.net.ultraq.thymeleaf.LayoutDialect"/>
</set>
</property>
</bean>
<bean class="org.thymeleaf.spring3.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine" />
</bean>
Is there something else that I can do to resolve this issue?
It depends on many many things and mainly on "where and how" you update your view. If you are using a IDE (Netbeans or Eclipse) it main depend on the IDE itself and on the deployement process.
Current organization on disk :
Source directories => [ on build ] => target or build directories => [ on deploy ] => tomcat directories
But IDE often tries to be developper's friendly and it can happen that target directories and tomcat directories are the same. But it also may depend of the IDE and its configuration.
Also when you save files under source webapp, the IDE may automatically copy them to target.
But this is not guaranteed by <property name="cacheable" value="false"/> of Thymeleaf config. All what it guarantees is that if a template is changed in tomcat directories, next request will use it.
So to be sure where the problem really comes, you will have to find where tomcat actually gets the templates and if those templates are modified.
(and I didn't even talked of browsers cache ...)
In Tomcat "Server Options", check "Serve modules without publishing" did the trick for me.

JNDI binding in JBOss for MQ

I need a little bit of help in configuring JBoss to work with MQ. I have created initial context in MQ using IBM MQ Explorer and have given a local directory for all bindings like file:/C:/jndi. I have created a connection factory for this initial context. Now JBoss documentation says to bind like this
<connection-definition class-name="com.ibm.mq.connector.outbound.ManagedConnectionFactoryImpl"
jndi-name="java:jboss/MQ.CONNECTIONFACTORY.NAME"
pool-name="MQ.CONNECTIONFACTORY.NAME">
I think I am missing some point here. How do I tell Jboss that my InitialContext bindings are in a directory. I have tried most of the combinations. May be I am not getting the concept right. Any pointers ?
When I try to access this MQ.CONNECTIONFACTORY.NAME from a test servlet I wrote I get javax.naming.NameNotFoundException . If I follow same steps in Java SE environment I am successfully able to establish a connection. I am new to application servers and the question might be naive
Regards
The description of the resources created via MQExplorer suggest that these have been put into JNDI backed by a File System context. This is perfectly fine, but what in theory needs to be done now is get JBOSS to read objects out that JNDI context rather than the usual JNDI provider provided by JBOSS. The settings that are in the connection definition extract are using the standard JBOSS JNDI context.
As an example of using JBOSS with the WebSphere MQ Resoruce Adapter have a look here http://pic.dhe.ibm.com/infocenter/wmqv7/v7r5/topic/com.ibm.mq.dev.doc/q031810_.htm
This links to an example set of definitions that store WMQ JMS administered objects in the JBOSS JNDI context.
This is an important question. I have used Spring for this, like this:
<util:properties id="remoteEnv">
<prop key="java.naming.provider.url">file:${my.config.path}/bindings</prop>
<prop key="java.naming.factory.url.pkgs">org.jboss.naming:org.jboss.naming.remote.client</prop>
<prop key="java.naming.factory.initial">com.sun.jndi.fscontext.RefFSContextFactory</prop>
<prop key="java.naming.security.principal">${mdb.user.name}</prop>
<prop key="java.naming.security.credentials">${mdb.user.pass}</prop>
</util:properties>
<bean id="remoteJNDITemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment" ref="remoteEnv" />
</bean>
<bean id="remoteJmsDestinationResolver" class="org.springframework.jms.support.destination.JndiDestinationResolver">
<property name="jndiTemplate" ref="remoteJNDITemplate" />
<property name="cache" value="true" />
</bean>
<jee:jndi-lookup id="senderQueue" jndi-name="MY_QUEUE_NAME" environment-ref="remoteEnv" />
<bean id="xamqconnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="remoteJNDITemplate"/>
</property>
<property name="jndiName" value="MYCONNECTIONFACTORYJNDINAME"/>
<property name="lookupOnStartup" value="false" />
<property name="proxyInterface" value="javax.jms.XAQueueConnectionFactory" />
</bean>
<bean id="xaMQSenderJMSTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<ref bean="xamqconnectionFactory" />
</property>
<property name="pubSubDomain">
<value>false</value>
</property>
<property name="defaultDestination">
<ref bean="senderQueue" />
</property>
<property name="destinationResolver" ref="remoteJmsDestinationResolver" />
</bean>
however using the configuration above we bypass the resource adapter. That's no problem otherwise but it prevents transactions from joining the JBoss transaction, so JMS messages are send immediately, not with transaction commit. I haven't found a fix for that yet.
com.sun.jndi.fscontext.RefFSContextFactory, that is used to read .bindings file, can be found at this dependency:
<dependency>
<groupId>com.sun.messaging.mq</groupId>
<artifactId>fscontext</artifactId>
<version>4.6-b01</version>
</dependency>

BoneCP sometimes cannot get config from spring property holder

I have been facing this issue for a while now. My config is as following
<!-- Load Properties Files -->
<context:property-placeholder location="classpath:*-${environment}.properties" ignore-unresolvable="true"/>
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="idleConnectionTestPeriodInMinutes" value="${boneCP.idleConnectionTestPeriodInMinutes}"/>
<property name="idleMaxAgeInMinutes" value="${boneCP.idleMaxAgeInMinutes}"/>
<property name="maxConnectionsPerPartition" value="${boneCP.maxConnectionsPerPartition}"/>
<property name="minConnectionsPerPartition" value="${boneCP.minConnectionsPerPartition}"/>
<property name="partitionCount" value="${boneCP.partitionCount}"/>
<property name="acquireIncrement" value="${boneCP.acquireIncrement}"/>
<property name="statementsCacheSize" value="${boneCP.statementsCacheSize}"/>
<property name="lazyInit" value="true"/>
<property name="maxConnectionAgeInSeconds" value="${boneCP.maxConnectionAgeInSeconds}"/>
</bean>
The project is running on Tomcat 7
On the local machine, the project deploy with no error as well as for the dev server. Unfortunately, the project cannot be deployed on dev server any more (server configuration remain same) while local machine is still fine. Every time I deploy the project on the dev server, Tomcat just hang at INFO: Deploying web application archive /etc/tomcat/webapps/project.war. But if I config BoneCP with real values, everything is fine.
Could any one tell me what's wrong with it?
It turned out to be the lazyInit problem. If I comment it out, the server can start normally. But now I'm facing the new issue though. Mybatis cannot access the db at all while the local machine is 100% fine. and yet dont throw any exception. But when I stop the server, I found the following exceptions
INFO: Illegal access: this web application instance has been stopped already. Could not load com.jolbox.bonecp.PoolUtil. The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.
java.lang.IllegalStateException
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1600)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
at com.jolbox.bonecp.DefaultConnectionStrategy.getConnectionInternal(DefaultConnectionStrategy.java:94)
at com.jolbox.bonecp.AbstractConnectionStrategy.getConnection(AbstractConnectionStrategy.java:90)
at com.jolbox.bonecp.BoneCP.getConnection(BoneCP.java:540)
at com.jolbox.bonecp.BoneCPDataSource.getConnection(BoneCPDataSource.java:131)
at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111)
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)
at org.mybatis.spring.transaction.SpringManagedTransaction.openConnection(SpringManagedTransaction.java:80)
at org.mybatis.spring.transaction.SpringManagedTransaction.getConnection(SpringManagedTransaction.java:66)
AND
INFO: Illegal access: this web application instance has been stopped already. Could not load org.apache.ibatis.reflection.ExceptionUtil. The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.
java.lang.IllegalStateException
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1600)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:363)
at sun.proxy.$Proxy15.selectList(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:195)
at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:124)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:90)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:40)
at sun.proxy.$Proxy45.selectByExample(Unknown Source)
Well it could be many things but its most likely
properties are not being replaced with the values you think
the database number of connections has been exceeded or the wrong host
A combination of 1 + 2
For #1 I would a make a separate bean that needs com.jolbox.bonecp.BoneCPDataSource as a dependency and have it print out the getters of BoneCPDataSource.
For #2 I would turn on as much logging as possible (see log4j or logback or whatever your logging framework is).

Spring JNDI datasource not recognized after upgrade to ActiveMQ 5.6.0

I tested a ActiveMQ 5.5.0 (fuse version) app in AMQ 5.6.0 and noticed that our Spring JNDI configured Oracle datasources aren't being found.
The only thing I changed in my applications was the pom.xml versions of AMQ/Spring (to match the 5.6 versions). Otherwise, I'm using the identical application code and configuration (activemq.xml, jndi.xml, etc), but my Spring JDBC DAOs (v3.0.5) are failing to find them.
No errors in the logs otherwise, just this Spring Application Context initialization error...
javax.naming.NameNotFoundException; remaining name 'jdbc/myDataSource'
here is the relevant Spring jndi config (conf/jndi.xml, included in conf/activemq.xml)...
<bean id="jndi" class="org.apache.xbean.spring.jndi.SpringInitialContextFactory"
factory-method="makeInitialContext" scope="singleton">
<property name="entries" ref="jndiEntries" />
</bean>
<util:map id="jndiEntries">
<entry key="jdbc/myDataSource">
<bean id="myDBCPDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.OracleDriver" />
...
then my application references it like this...
<bean id="myDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>jdbc/myDataSource</value>
</property>
</bean>
<bean id="messageDAO" class="com.mycompany.MessageDAOImpl">
<property name="dataSource" ref="myDataSource" />
</bean>
That said, I tested without using JNDI (instead just hardcoded the datasource in my app) and everything works as expected. So that should rule out everything except the Spring JNDI registration/lookup of the datasource, etc.
So, what am I missing?
ActiveMQ has a dependency into xbean-spring, which you are using as a JNDI provider. It is likely that the transitive Xbean dependency has changed because of the upgrade to ActiveMQ 5.6.0.
I found the issue, I added a jndi.properties file under the /conf directory containing the following and it works fine now (didn't need this under AMQ 5.5...strange)...
java.naming.factory.initial = org.apache.xbean.spring.jndi.SpringInitialContextFactory

Weblogic Spring Dependency Injection from flat-files on the file-system

I have an application deployed into Oracle Weblogic 10.3. In my .ear files, I use spring injection from xml files in the ear files. I would like to also perform dependency injection from xml files placed on the server file-system. We do something similar to this in Karaf, where we place our configuration files for bundles in the conf directory in the server itself. Is there a similar way to do this in weblogic?
You can ask spring to read properties from file systems as below;
<!-- Reads application properties and uses them in the application context -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="true"/>
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="locations">
<list>
<value>file:D:\somefolder\application.properties</value>
<value>classpath:com/foo/sp.properties</value>
</list>
</property>
</bean>

Resources