Java - Spring property file configuration for jar file - spring

Java-Spring I have modules based project, i have module for DAO layer and module for business layer which is dependent upon DAO layer and web layer dependent upon DAO layer and business layer.
I am using maven for project compilation. and jar of every components are group under web projects lib folder.
Problem is i have spring context file and .property file inside DAO jar and following is my configuration but i spring unable to load properties i also tried prefixing value="classpath:abc.properties but it didn't work.
When i open the DAO jar both spring context and .properties files are on root.
<bean id="applicationProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="abc.properties" />
</bean>
<bean id="cmfModelDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="${jdbc.ConnectionUrl}"/>
<property name="username" value="${jdbc.Username}"/>
<property name="password" value="${jdbc.Password}"/>
</bean>
any idea how to quick fix this issue ?

I have a multi-module web project with Spring using the following code:
<context:property-placeholder location="classpath:env/env.properties" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${env.datasource.driver}" />
<property name="url" value="${env.datasource.url}" />
<property name="username" value="${env.datasource.username}" />
<property name="password" value="${env.datasource.password}" />
</bean>
Don`t forget to verify the namespace url in the xml file:
xmlns:context="http://www.springframework.org/schema/context";
The folder env must be in classpath, so Spring can find it. My properties file is also inside a jar, and it`s working just fine.

I had that error and int might have to do with the way you are initializing the context, for example in my web app the problem was somehing with the filter I setup in the web.xml file. Also I end up using not an xml file but an Annotated Config Class and placed this in the web.xml:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.myapp.configuration.SpringConfig</param-value>
</context-param>
If you really want to use an xml file you must change the AnnotationConfigWebApplicationContext for an XmlWebApplicationContext. You should tell us how are you initilizing your context (like the code or web.xml if this is does not solve your issue)

Related

Use values from properties file in web.xml

I am a begginer in Spring and encountered the following problem.
I have the following files:
app.properties
applicationContext.xml
web.xml
Within app.properties I have the value app.env=dev
In applicationContext.xml:
<bean class="org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="true" />
<property name="location">
<value>app.properties</value>
</property>
</bean>
I want to use the app.env from the properties file in web.xml like this:
<context-param>
<param-name>ENV</param-name>
<param-value>${app.env}</param-value>
</context-param>
I am using ${app.env} without problems in applicationContext.xml.
I have found discussions that state you can push values into web.xml from a properties file but I have also found people saying it is not possible (usually older posts).
The issue is the placeholder ${app.env} in web.xml is not replaced by the value from the properties file. Is it possible to do it? If so what am I missing.

Not Rolling Back Spring Transaction From ZK

I am facing a problem while calling the service method written in Spring Sevice that is injected in MVVM in that method I am saving one object and after that doing some other value fatching method call that throw exception and I want that while throwing that exception my Transaction rollback my service method part are as under CeilingServiceIMPL:
CeilingSheet ceilingSheet = new CeilingSheet();
ceilingSheet.setFiscalYear(fiscalYear);
ceilingSheet.setStatus(ECeilingSheetStatus.NEW);
ceilingSheet = saveCeilingSheet(ceilingSheet).getResult();
CeilingCategory ceilingCategory1 = null;
try {
ceilingCategory1 = categoryQueryService.findCeilingCategoryByCode(
"01").getResult();
} catch (ObjectNotFoundException ex) {
throw new RequestException(1234, ceilingCategory1);
}
if RequestException throws , I am expecting that my record that I saved before also rollback. I have making the service Transaction by annotating as
#Transactional(rollbackFor = RequestException.class)
The bean is injected with
#WireVariable(ICeilingSheetService.NAME) private ICeilingSheetService ceilingSheetService;
When I tried this method to call from junit test case it rolling back fine , but when I integrate it with ZK zul page and View Model by autowired services it stop rolling back and even if my code throws RequestException my CeilingSheet are persisting.
My ZK web.xml is
<!-- Spring can be easily integrated into any Java-based web framework.
All you need to do is to declare the ContextLoaderListener in your web.xml
and use a contextConfigLocation <context-param> to set which context files
to load. If you don't specify the contextConfigLocation context parameter,
the ContextLoaderListener will look for a /WEB-INF/applicationContext.xml
file to load. Once the context files are loaded, Spring creates a WebApplicationContext
object based on the bean definitions and puts it into the ServletContext. -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/application-context.xml
</param-value>
</context-param>
<!-- LOGGER -->
<context-param>
<param-name>log4j-config-location</param-name>
<param-value>WEB-INF/log4j.properties</param-value>
</context-param>
<!-- Loads the Spring web application context -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- end of spring configuration -->
<description><![CDATA[My ZK Application]]></description>
<display-name>IFMIS User Interface</display-name>
<!-- //// -->
<!-- ZK -->
<listener>
<description>ZK listener for session cleanup</description>
<listener-class>org.zkoss.zk.ui.http.HttpSessionListener</listener-class>
</listener>
<servlet>
<description>ZK loader for ZUML pages</description>
<servlet-name>zkLoader</servlet-name>
<servlet-class>org.zkoss.zk.ui.http.DHtmlLayoutServlet</servlet-class>
<!-- Must. Specifies URI of the update engine (DHtmlUpdateServlet). It
must be the same as <url-pattern> for the update engine. -->
<init-param>
<param-name>update-uri</param-name>
<param-value>/zkau</param-value>
</init-param>
<!-- Optional. Specifies whether to compress the output of the ZK loader.
It speeds up the transmission over slow Internet. However, if you configure
a filter to post-processing the output, you might have to disable it. Default:
true <init-param> <param-name>compress</param-name> <param-value>true</param-value>
</init-param> -->
<!-- [Optional] Specifies the default log level: OFF, ERROR, WARNING, INFO,
DEBUG and FINER. If not specified, the system default is used. <init-param>
<param-name>log-level</param-name> <param-value>OFF</param-value> </init-param> -->
<load-on-startup>1</load-on-startup><!-- Must -->
</servlet>
<servlet-mapping>
<servlet-name>zkLoader</servlet-name>
<url-pattern>*.zul</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>zkLoader</servlet-name>
<url-pattern>*.zhtml</url-pattern>
</servlet-mapping>
<!-- [Optional] Uncomment it if you want to use richlets. <servlet-mapping>
<servlet-name>zkLoader</servlet-name> <url-pattern>/zk/*</url-pattern> </servlet-mapping> -->
<servlet>
<description>The asynchronous update engine for ZK</description>
<servlet-name>auEngine</servlet-name>
<servlet-class>org.zkoss.zk.au.http.DHtmlUpdateServlet</servlet-class>
<!-- [Optional] Specifies whether to compress the output of the ZK loader.
It speeds up the transmission over slow Internet. However, if your server
will do the compression, you might have to disable it. Default: true <init-param>
<param-name>compress</param-name> <param-value>true</param-value> </init-param> -->
<!-- [Optional] Specifies the AU extension for particular prefix. <init-param>
<param-name>extension0</param-name> <param-value>/upload=com.my.MyUploader</param-value>
</init-param> -->
</servlet>
<servlet-mapping>
<servlet-name>auEngine</servlet-name>
<url-pattern>/zkau/*</url-pattern>
</servlet-mapping>
My application-context.xml
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>/WEB-INF/database.properties</value>
<value>/WEB-INF/msg-database.properties</value>
</list>
</property>
</bean>
<tx:annotation-driven />
<context:annotation-config />
<context:component-scan base-package="my.service" />
<import resource="hibernate-context.xml" />
My hibernat-context.xml
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass">
<value>${jdbc.driverClassName}</value>
</property>
<property name="jdbcUrl">
<value>${jdbc.url}</value>
</property>
<property name="user">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
<property name="maxPoolSize" value="${jdbc.maxPoolSize}" />
<property name="minPoolSize" value="${jdbc.minPoolSize}" />
<property name="maxStatements" value="${jdbc.maxStatements}" />
<property name="testConnectionOnCheckout" value="${jdbc.testConnection}" />
</bean>
<!-- bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"> <value>${driverClassName}</value> </property>
<property name="url"> <value>${url}</value> </property> <property name="username">
<value>${username}</value> </property> <property name="password"> <value>${password}</value>
</property> </bean -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<list>
<value>my.domain.class</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="jadira.usertype.autoRegisterUserTypes">${jadira.usertype}</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
Please advice ...
The first step in such cases is always to enable logging at level DEBUG for org.springframework.orm.hibernate4.HibernateTransactionManager. That will show you what Spring is doing and why.
For example, it will show you when it detects an exception and when it does a rollback or a commit. You can also set breakpoints in this code to see what is going on. It's pretty straightforward.
Knowing a bit about ZK, my guess is that you have new CeilingServiceIMPL() somewhere in the ZK code because you couldn't figure out how to inject Spring beans into a controller. This effectively renders all #Transactional useless.
You must get the bean from spring. Check out http://www.zkoss.org/product/zkspring and the documentation at Using Spring Variable Resolver how to wire beans with ZK.
I found the solution :
Reason : In My application we have the requirement to show the User messages based on the number thrown by the exception , for this we have a separate message-hibernate-context.xml file with seperate
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="messageSessionFactory" />
</bean>
and one is already with hibernate-context.xml
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
and the above both xml file called from my application-context.xml as
<import resource="hibernate-context.xml" />
<import resource="message-hibernate-context.xml" />
So after code thrown exception based on key thrown , my user-message bean trying to load separate Transaction Manager and old transaction committed and new Hibernate session starts that was going to rollback and since this is new Transaction so It does not found anything to rollback.
Once I removed other Transaction Manager it start working .
Thanks All for support...

Migrating JAX-WS RI to Spring controlled service without SOAP?

Excuse me if I use incorrect terminology, I'm a bit new to this. I've created a web service using Sun's JAX-WS RI "Provider" implementation. We send this service plain XML, and it responds in plain XML. I've tried to move this into Spring so the services are accessible via Spring context, but now it's looking for a SOAP envelope, which we are not using. How do I tell it I am not using SOAP?
My web.xml looks like this:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<display-name>MyServiceImpl</display-name>
<servlet-name>MyServiceImpl</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSSpringServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MyServiceImpl</servlet-name>
<url-pattern>/myServiceUrl</url-pattern>
</servlet-mapping>
And here's my applicationContext.xml:
<!-- this bean implements web service methods -->
<bean id="myService" class="com.acme.MyServiceImpl" />
<bean class="com.sun.xml.ws.transport.http.servlet.SpringBinding">
<property name="url" value="/myServiceUrl" />
<property name="service">
<bean class="org.jvnet.jax_ws_commons.spring.SpringService">
<property name="bean">
<ref local="myService" />
</property>
<property name="impl" value="com.acme.MyServiceImpl" />
</bean>
</property>
</bean>
My service class looks something like this:
#javax.xml.ws.WebServiceProvider
#javax.xml.ws.ServiceMode(value=javax.xml.ws.Service.Mode.MESSAGE)
public class MyServiceImpl implements Provider<Source> {
#Override
public Source invoke(Source source) {
... // unmarshal the source object using JAXB, do work, marshall a response back
}
The error message I receive upon sending the service my basic XML is:
<?xml version="1.0" encoding="UTF-8"?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope"><faultcode>S:Client</faultcode><faultstring>Couldn't create SOAP message due to exception: unexpected XML tag. expected: {http://schemas.xmlsoap.org/soap/envelope/}Envelope but found: {}Request</faultstring></S:Fault></S:Body></S:Envelope>
How do I rid the SOAP?
Found it; need to specify the bindingId (which was defined in the sun-jaxws.xml previously) on the web service bean:
<property name="service">
<bean class="org.jvnet.jax_ws_commons.spring.SpringService">
<property name="bean">
<ref local="myService" />
</property>
<property name="impl" value="com.acme.MyServiceImpl" />
<property name="bindingID" value="http://www.w3.org/2004/08/wsdl/http" />
</bean>
</property>

Bean Context in Spring

The application works perfectly with the following config files:
My Web.XML is as follows
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/spring/mvc-dispatcher-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/classes/spring/spring-context.xml,
/WEB-INF/classes/spring/spring-security.xml
</param-value>
</context-param>
<!-- Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
My mvc-dispatcher-servlet
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<context:component-scan base-package="biz.canisrigel.slapMe" />
<!-- enable autowire -->
<context:annotation-config />
My spring-context.xml is
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<context:component-scan base-package="biz.canisrigel.slapMe" />
<!-- enable autowire -->
<context:annotation-config />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/slapMe" />
<property name="username" value="root" />
<property name="password" value="adminadmin" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="typeAliasesPackage" value="biz.canisrigel.slapMe.bean" />
</bean>
<!-- scan for mappers and let them be autowired -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="biz.canisrigel.slapMe.mapper" />
</bean>
I couldn't run spring security properly cause earlier spring-context.xml was the xml config file for dispatcher servlet for MVC. So I moved spring-context to contextConfigLocation. But then I had to provide something to dispatcher servlet.
My problem is that mvc-dispatcher-servlet.xml and spring-context is having same data. If I remove mvc-dispatcher its an error. If I don't place the contents of mvc-dispatcher in spring context then also error occurs.
Where am I going wrong in my understanding of concepts.
A few things:
Your web.xml looks correct
The InternalResourceViewResolver should only exist in your mvc-dispatcher-servlet.xml since it is directly related to MVC -- remove it from your spring-context.xml
You can have context:component-scan in both configuration files, but they should be scanning different packages. The one in your servlet xml will generally be component scanning your controller packages (and anything else directly related to MVC), and the one in your parent spring context xml will generally be scanning your services, DAOs, etc. In general, your component scan packages should be very specific; you should never point it towards the base package of your entire application!
You can remove context:annotation-config -- it is redundant if you have context:component-scan
Your MVC context should have only configuration related to MVC which generally includes ViewResolvers, FileUpload, PropertyFiles, Message/Theme Resolvers etc. Your applicationContext will have beans related to DAO, Service and other utils. The security file should have security configuration. To understand better and to know good/recommended practices, check out the spring greehouse code.

Loading log4j.xml from outside of war file

For my spring application, I have a requirement to move log4j.xml outside of war file. I have been searching for solutions, and found following ways:
org.springframework.web.util.Log4jConfigListener: this did not work as war is not expanded on tomcat.
Passing jvm property (-Dlog.Localtion=....): Since log4j file is application specific, I do not think this is good way to do this.
I am wondering what is best way to solve this. I believe Spring should make it easy someway, it's just I don't much about it.
You can specify the location of your log4j.xml in your context config file:
<bean id="log4jInitialization"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass"
value="org.springframework.util.Log4jConfigurer" />
<property name="targetMethod" value="initLogging" />
<property name="arguments">
<list>
<value>/any/path/log4j.xml</value>
</list>
</property>
</bean>
Source http://helpdesk.objects.com.au/java/how-to-specify-log4j-configuration-in-spring-application
You can check org.springframework.util.Log4jConfigurer. You can pass the location of log4j.xml to this class.It also takes care of resolving property place holders.
You can use org.springframework.web.util.Log4jConfigListener in your web.xml - just add this elements:
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>../path/to/config</param-value>
</context-param>

Resources