Very useful link that explains what to do to make a web app fully UTF-8 compliant:
http://stackoverflow.com/questions/138948/how-to-get-utf-8-working-in-java-webapps
Especially the use of a servlet filter, or the dedicated SpringCharacterEncodingFilter has been very useful to filter out the more cumbersome cases (browser that supposedly sends UTF-8 encoded data but still the business logic doesn't parse them that way).
<filter>
<filter-name>encoding-filter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>FALSE</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding-filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Further information:
http://wiki.apache.org/tomcat/FAQ/CharacterEncoding
Thursday, May 14, 2015
Thursday, August 13, 2009
How to convert a web application using a datasource defined in Tomcat's context.xml into a web application running on Jboss and using an internal one
Example is for an Oracle Datasource and a MyApp web application, but is identical for other vendor types/web applications.
Initial situation on Tomcat 6
Final situation on Jboss 5
Initial situation on Tomcat 6
- JDBC driver in $TOMCAT/lib
- context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/MyApp">
<Loader delegate="true"/>
<!-- Name must match resource-ref in web.xml and bean with id="datasource" in applicationContext.xml!
<Resource name="jdbc/MyDs"
auth="Container" type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:@192.168.0.107:1521:XE" username="vatengine" password="vatengine"
removeAbandoned="true" maxActive="-1" maxIdle="-1" maxWait="-1"/>
</Context>
- web.xml:
...
<resource-ref>
<description>MyDs Oracle Datasource</description>
<res-ref-name>jdbc/MyDs</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
...
- Spring's applicationContext.xml:
...
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/MyDs"/>
</bean>
...
Final situation on Jboss 5
- add JDBC driver to $JBOSS/server/type_of_server/lib, in our case $JBOSS/server/default/lib
- MyDs-ds.xml: this file defines the Jboss datasource and has to be added to $JBOSS/server/type_of_server/deploy, in our case $JBOSS/server/default/deploy
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<local-tx-datasource>
<jndi-name>jdbc/MyDs</jndi-name>
<connection-url>jdbc:oracle:thin:@192.168.0.107:1521:XE</connection-url>
<driver-class>oracle.jdbc.OracleDriver</driver-class>
<user-name>vatengine</user-name>
<password>vatengine</password>
<valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker</valid-connection-checker-class-name>
</local-tx-datasource>
</datasources>
- web.xml and applicationContext.xml stay identical
- context.xml: the datasource declaration can be removed, since we will be creating one in Jboss (but it seems leaving it doesn't do harm)
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/MyApp">
<Loader delegate="true"/>
</Context>
- jboss.web.xml: this file has to be added to the web application's WEB-INF directory contains glue logic between web.xml and Jboss resource declarations
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<resource-ref>
<res-ref-name>jdbc/MyDs</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<jndi-name>java:jdbc/MyDs</jndi-name>
</resource-ref>
</jboss-web>
Tuesday, August 11, 2009
Converting an application using an internal datasource to one using a JNDI datasource
Elaboration for Tomcat 6 and Oracle 10; other application or db servers are similar.
1. Copy the jdbc driver jar (ojdbc14.jar) to $TOMCAT_HOME/lib
2. To the application's context.xml, add the following lines:
where XXX is the name the datasource will take in the JNDI tree, and url, username and password keep the real values used before.
The other parameters may be finetuned at will. removeAbandoned="true" makes sure that that abandoned dB connections are removed and recycled.
3. To the application's web.xml, add the following:
where XXX matches the JNDI name chosen before.
4. Within the application, use the datasource's JNDI name when referring to it: java:comp/env/jdbc/XXX
for instance, in Spring's applicationContext.xml, one can add:
and inject this bean in other beans that need a datasource.
5. Since the Oracle driver will already be loaded by Tomcat's classloader at the startup of the application, it isn't needed to deploy it with the application, it's only needed to compile. Hence, in Eclipse, in the project's properties->Java EE Module Dependencies, unmark the dependency on the oracle driver (ojdbc14.jar), or remove it from the dist target within a custom Ant script.
Source: http://tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html
1. Copy the jdbc driver jar (ojdbc14.jar) to $TOMCAT_HOME/lib
2. To the application's context.xml, add the following lines:
<Resource name="jdbc/XXX"
auth="Container" type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
url="url" username="usr" password="pass"
removeAbandoned="true" maxActive="-1" maxIdle="-1" maxWait="-1"/>
where XXX is the name the datasource will take in the JNDI tree, and url, username and password keep the real values used before.
The other parameters may be finetuned at will. removeAbandoned="true" makes sure that that abandoned dB connections are removed and recycled.
3. To the application's web.xml, add the following:
<resource-ref>
<description>Oracle Datasource</description>
<res-ref-name>jdbc/XXX</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
where XXX matches the JNDI name chosen before.
4. Within the application, use the datasource's JNDI name when referring to it: java:comp/env/jdbc/XXX
for instance, in Spring's applicationContext.xml, one can add:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/XXX"/>
</bean>
and inject this bean in other beans that need a datasource.
5. Since the Oracle driver will already be loaded by Tomcat's classloader at the startup of the application, it isn't needed to deploy it with the application, it's only needed to compile. Hence, in Eclipse, in the project's properties->Java EE Module Dependencies, unmark the dependency on the oracle driver (ojdbc14.jar), or remove it from the dist target within a custom Ant script.
Source: http://tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html
Wednesday, July 22, 2009
Tips and hints when using Spring Web Services
Some things I noted while trying to set up a Spring web services application, that obeys to WS-Addressing and SoapAction headers.
- Bottom-up approach:
- Write WSDL and XSD, adding soapAction descriptors and enabling WS-Addressing (see below)
- Use JAXB to generate beans
- Set up Spring WS configuration: marshaller, interceptors, endpoint and endpoint mapping
- Create the endpoint class (@endpoint) and start populating it with web methods, making them match with the WSDL operations, adding annotations @Action and @SoapAction for resp. SoapAction and WS-Addressing endpoints. Use the generated beans for input/output
- When calling the application, if an "argument type mismatch" SoapFault is returned:
- logically, check if you're calling the correct Action
- sometimes it is/isn't needed to nest arguments/return parameters in a JAXBElement; if it isn't needed, this error is returned
- To make WS-Addressing work
- add the WSAW namespace in the wsdl: xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
- in the same WSDL, add >wsaw:UsingAddressing wsdl:required="true"/< in the binding part. It's not needed to define Actions in the WSDL, IF you're already defining a SoapAction: as a default this one will be used for the WS-Addressing too.
- using Spring WS annotations, add @org.springframework.ws.server.endpoint.annotation.Endpoint at the beginning of the class to declare the class as an endpoint; and for each web method, add @org.springframework.ws.soap.addressing.server.annotation.Action and
@org.springframework.ws.soap.server.endpoint.annotation.SoapAction
annotations on top of them, ex.
@SoapAction(Constants.SOAP_LOCATION_URL_CONSULTA_CONTRATO)
@Action(value=Constants.SOAP_LOCATION_URL_CONSULTA_CONTRATO)
public JAXBElementconsultaContrato(final ConsultaContrato consultaContrato) {
...
}
Monday, June 15, 2009
Struts2: form not submitting
When using Struts2, here are some hints about what may be happening if after submit the data of your form isn't available within the corresponding action:
Check if on click you're effectively performing a submit and not just merely following a link; only the<s:submit>tag should be used or a link which calls ajavascript:form.submit()!
Be sure that you have a public setter (and getter) within your action for all the variables you're submitting, otherwise the (private) member variables within your action will never receive a value!
Thursday, June 11, 2009
Changes needed when switching from Struts2 v.2.0.11.2 to v.2.1.6
When using an old and working application, based upon Struts2 v.2.0.11.2, as the base for a new application using Struts2 v.2.1.6, I encountered I had to make the following modifications in struts.xml:
- change all type="redirect-action" into type="redirectAction"
- Because the org.apache.struts2.views.tiles.TilesResult isn't included anymore in the struts jar, I had to comment
<result-types>
<result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult"/>
</result-types>
Update: on hindsight, the second error was caused by a missing tiles jar!
Thursday, September 18, 2008
Custom Ant task to read version number from Constants.class file
Problem:
To keep track of a version number, we used to have it in two files: once in a Constants.java for the application itself, and once in the Ant build script in order to have a version number in the resulted WAR's META-INF section. This duplication was cumbersome and error-prone, we always had to update both files and make sure the version numbers matched; in a distributed develop/build environment, this was a nighmare.
Solution: We decided to stick to one version number, in the Constants.java file and to create a custom Ant taskdef to retrieve this number from the compiled class file at the end of the building process.
We have the following parts:
We compiled the VersionPropertyRetriever.java file through another xml file, to be executed with Ant, buildVersionPropertyClass.xml:
To keep track of a version number, we used to have it in two files: once in a Constants.java for the application itself, and once in the Ant build script in order to have a version number in the resulted WAR's META-INF section. This duplication was cumbersome and error-prone, we always had to update both files and make sure the version numbers matched; in a distributed develop/build environment, this was a nighmare.
Solution: We decided to stick to one version number, in the Constants.java file and to create a custom Ant taskdef to retrieve this number from the compiled class file at the end of the building process.
We have the following parts:
- in our build.xml, the following taskdef:
<taskdef name="versionPropertyRetriever" classname="VersionPropertyRetriever" classpath="${basedir}"/>
and the following task call
<versionPropertyRetriever name="app.version" className="com.datamat.care.base.Constants" classpath="${basedir}; ${build.web.home}/WEB-INF/classes"/>
which retrieves the version number and makes it available as the app.version property. - a VersionPropertyRetriever java class, extending Ant's Property.java, whose main purpose is to retrieve the value of the VERSION constant in the className class through introspection. Besides adding a getter and setter for the className attribute, its main business logic is implemented within the private parseClass method:
private void parseClass() {
try {
ClassLoader cL = getProject().createClassLoader(classpath);
Class c = cL.loadClass(className);
if (c==null)
throw new BuildException("Couldn't find the Constants class");
Field field = c.getField("VERSION");
if (field==null)
throw new BuildException("'VERSION' field not found within Constants.java file");
Object value = field.get(null);
if (value==null)
throw new BuildException("Version not set within Constants.java file");
// all fine -> add as a property
addProperty(name,value.toString());
}
catch(Exception e) {
throw new BuildException("Unexpected Exception: " + e.getMessage());
}
}
We compiled the VersionPropertyRetriever.java file through another xml file, to be executed with Ant, buildVersionPropertyClass.xml:
<!--
Script to compile the VersionProperty class starting from the VersionProperty.java file
-->
<project name="buildVersionPropertyClass" default="main" basedir="./">
<property file="build.properties"/>
<path id="compile.classpath">
<!-- Include all JAR files needed to compile -->
<fileset dir="${basedir}" includes="*.class"/>
<fileset dir="${libraries.home}/Ant" includes="*.jar"/>
</path>
<target name="main" depends="" description="Compile java file">
<echo message="Compiling"/>
<javac srcdir="${basedir}" destdir="${basedir}" includes="*.java">
<classpath refid="compile.classpath"/>
</javac>
</target>
</project>
Subscribe to:
Posts (Atom)
