Nothing special. just bits and pieces about my life, my career and my loves.

Tuesday, July 01, 2008

Weblogic JWSC and Maven - Pom.xml

And my pom file look like this:

build->plugins

<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<tasks>
<property name="build.compiler"
value="extJavac" />
<ant inheritRefs="true"
antfile="mvn-build.xml" dir=".">
<property
value="${project.build.directory}" name="build.dir" />
<property
value="${project.artifactId}" name="artifact.id" />
<property value="${project.version}"
name="version" />
<property
refid="maven.compile.classpath" name="dependencies" />
<target name="all" />
</ant>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
<execution>
<id>clean</id>
<phase>clean</phase>
<configuration>
<tasks>
<property name="build.compiler"
value="extJavac" />
<ant inheritRefs="true"
antfile="mvn-build.xml" dir=".">
<property
value="${project.build.directory}" name="build.dir" />
<property
refid="maven.compile.classpath" name="dependencies" />
<target name="clean" />
</ant>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>

Monday, April 07, 2008

Weblogic JWSC and Maven

I decided to use Weblogic Java Web Services (JWS) instead of other web services stack like Axis2, Metro for web services implementation at Optus.

The reasons behind it are:
simpler deployment model comparing to Axis2 - AAR really sucks
Metro only supports Netbeans to generate the WS policy files

Weblogic 9.2/10 provides an ant task for you to generate the artifacts from the JWS file. However, unlike Metro, it doesn't support maven by default. In order to get around with it, I have to use the Antrun plug-in to invoke my ant build scripts.

Here is my ant script:

<?xml version="1.0" ?>
<project default="all">
<!-- Project Specific Settings, you need to change this section for different project -->
<property name="packageName" value="com/mycompany/ws/jws" />
<property name="contextPath" value="security" />
<property name="serviceName" value="SecurityService" />

<!-- it's a convention to put wsdl under the src/main/resources/wsdl -->
<property name="srcWsdlDir" value="src/main/resources/wsdls" />

<!-- Setting the CLASSPATH -->
<property environment="env" />
<echo>###############################################################</echo>
<echo>${env.WL_HOME}</echo>
<echo>${env.JAVA_HOME}</echo>
<echo>###############################################################</echo>
<echo>${dependencies}</echo>
<echo>###############################################################</echo>
<path id="project.class.path">
<path path="${dependencies}" />
<path path="${env.WL_HOME}/server/lib/weblogic.jar" />
</path>

<!-- define weblogic specific ant task -->
<taskdef name="wsdlc" classpathref="project.class.path" classname="weblogic.wsee.tools.anttasks.WsdlcTask" />
<taskdef name="jwsc" classpathref="project.class.path" classname="weblogic.wsee.tools.anttasks.JwscTask" />

<!-- create java (jws, interface and DTOs) sources from wsdl -->
<target name="wsdlc">
<wsdlc srcWsdl="src/main/resources/wsdls/${serviceName}.wsdl" destJwsDir="target/jws" destImplDir="target/impl" />

<!-- Execute again to get the source code -->
<wsdlc explode="true" srcWsdl="src/main/resources/wsdls/${serviceName}.wsdl" destJwsDir="target/jws" destImplDir="target/impl" />
<echo>generate-from-wsdl completed</echo>

<!-- copy generated files like DTOs-->
<copy todir="target/generated-sources" includeEmptyDirs="false">
<fileset dir="target/jws">
<!--<exclude core package>-->
<exclude name="**/core/**/*.java" />
<include name="**/*.java" />
</fileset>
</copy>

<!-- check jws file exists or not -->
<available file="src/main/java/${packageName}/Jws${serviceName}.java" property="jwsFile.exists" />
<antcall target="jws_check" />
<echo>finish copy</echo>
</target>

<!-- copy jws file to source if neccessary -->
<target name="jws_check" unless="jwsFile.exists">
<echo>copy jws file now as it doesn't exist</echo>
<copy todir="src/main/java/${packageName}" includeEmptyDirs="false" flatten="true">
<fileset dir="target/impl">
<include name="**/${serviceName}Impl.java" />
</fileset>
</copy>
<move file="src/main/java/${packageName}/${serviceName}Impl.java" tofile="src/main/java/${packageName}/Jws${serviceName}.java" />
</target>

<!-- create weblogic deployment desciptors from jws file -->
<target name="jwsc" if="jwsFile.exists">
<echo>build.xml is called</echo>

<jwsc debug="true" tempdir="target/temp" keepgenerated="yes" srcdir="src/main/java" classpathref="project.class.path" destdir="target">
<module explode="true" contextPath="${contextPath}">
<jws file="${packageName}/Jws${serviceName}.java" compiledWsdl="target/jws/${serviceName}_wsdl.jar">
<WLHttpTransport serviceUri="${serviceName}" portName="${serviceName}Port" />
</jws>

<!-- add the web service to our template web.xml -->
<descriptor file="src/main/resources/wlartifacts/web.xml" />
</module>
</jwsc>

<!-- insert our service name as the URL pattern of the JAMon filter-->
<replace file="target/jws/WEB-INF/web.xml" token="@FILTER_URL_PATTERN@" value="/${serviceName}"/>

<echo>jwsc completed</echo>
</target>

<!-- copy generated binary files to Maven, so that it will be archived in the WAR file -->
<target name="copy_files" if="jwsFile.exists">

<copy todir="src/main/webapp/WEB-INF" includeEmptyDirs="false" failonerror="false">
<fileset dir="target/jws/WEB-INF">
<exclude name="**/*.class" />
<exclude name="classes/*" />
</fileset>
</copy>
<!-- copy generated java sources again-->
<copy todir="target/generated-sources" includeEmptyDirs="false" failonerror="false">
<fileset dir="target/jws">
<exclude name="**/core/**/*.java" />
<include name="**/*.java" />
</fileset>
</copy>

<copy todir="src/main/webapp" includeEmptyDirs="false" failonerror="false">
<fileset dir="target/jws">
<include name="wsdls/**" />
</fileset>
</copy>
</target>

<!-- clean up generated files in WEB-INF -->
<target name="clean">
<echo>cleaning all generated files</echo>
<delete failonerror="false" includeemptydirs="true">
<fileset dir="src/main/webapp/WEB-INF" includes="**/*" />
</delete>
<delete failonerror="false" includeemptydirs="true">
<fileset dir="src/main/webapp">
<include name="wsdls/**" />
</fileset>
</delete>
</target>

<target name="all" depends="wsdlc,jwsc,copy_files" />

</project>

Thursday, November 15, 2007

Here I come !!!

With the release of its SDK yesterday, Android, Google's new open source mobile operating system, has announced a developer challenge with $10 million in awards.

The 50 most promising mobile apps built for the platform will each receive $25,000 award to fund further development. Those selected will then be eligible for even greater recognition via ten $275,000 awards and ten $100,000 awards.

http://code.google.com/android/adc.html

I wish I can come up some idea over this weekend



Thursday, November 08, 2007

Java/Spring i18n



My manager asked me to create a Japanese version of Michael Page Mobile Website few days ago, I thought it would be fairly straight forward as I already defined all the texts in a properties file. I guessed all I need to do is just created a message_ja_JP.properties file and find out a way how to set the locale for the JSTL fmt:message tag.

Of course, It ended up to be much more complicated than I expected. Hence I decide to blog what I had done for further references.

  1. open message.properties in a MS Word. Covert all the values in japanese and then save the file as message_ja_JP.txt, make sure to encode the file to unicode format.
  2. execute $JAVA_HOME/bin/native2ascii -encoding UnicodeLittle message_ja_JP.txt message_ja_JP.properties. Open message_ja_JP.properties with MS-Word with UTF-8 encoding. You will notice that all the text is covert to something like keyName=\u826f\u3092\u696d\u754c
  3. Defined a bean named "localeResolver" in the spring web application context, this mean must implement org.springframework.web.servlet.LocaleResolver interface. Basically, jstl will use this resolver to resolve the locale.
  4. Added <%@ page pageEncoding="UTF-8" %> at the top of every single JSPs and <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" /> between the html head tag.
  5. Create a Servlet Filter and put it the end of the filter chain.
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding("charset=UTF-8"); response.setContentType("UTF-8"); chain.doFilter(request, response); }
  6. This filter must put after Sitemesh filter (if applicable)
  7. Use org.springframework.mail.javamail.MimeMessagePreparator and org.springframework.mail.javamail.JavaMailSender instead of SimpleMessage and MailSender, this allows you to encode the character to UTF-8 format.
  8. IF you use DisplayTag for paging, you need to add locale.resolver=org.displaytag.localization.I18nSpringAdapter in the displaytag.properties file and then create displaytag_ja_JP.properties for Japanese messages.
  9. Use org.springframework.context.MessageSource if you need to lookup localized message in the service layer, by injectMessageSource instance (e.g. org.springframework.context.support.ResourceBundleMessageSource) to your service class.
You should now able to display the proper message :)
I also found this link very useful.

Thursday, October 25, 2007

Buildix + Maven2 Part 3

When using maven2, instead of downloading all the jars from the internet, you should setup your local internal repository and use it as a maven proxy. It's pretty simple, if you try a retrieve a jar file that is not exists in the internal repository, the internal repository will download it from the internet and then cache it, so that next time when you need it again, you can get it off the cache. This will save your time and bandwidth. The other purpose of using an internal repository is you can publish your jar/war/ear files, so that it can be used by other team members.

There are many open source maven2 repositories out there, e.g. Archive, Proximity and Artifactory. I've chosen Artifactory because it's the most active project. It has good documentation and it's is very simple to install and use.

Artifactory can be run as a standalone java application or you can deploy it as a war file. Since Buildix comes with tomcat5, so I decided to put it there.


Download Artifactory and then extract it to /usr/share/artifactory-1.X.X as root

Add the -Dartifactory.home argument in /usr/share/tomcat5/bin/catalina.sh
JAVA_OPTS=" -Xms128m -Xmx384m -Dartifactory.home=/usr/share/artifactory-1.2.2 "
export JAVA_OPTS

Copy the configuration file to /usr/share/artifactory-1.X.X/etc/artifactory.config.xml

Create 3 directories logs, backup and data under /usr/share/artifactory-1.X.X and then chown these directories to cruise

To deploy Artifactory into tomcat, you need to create a simlink in /usr/share/tomcat5/webapps

Finally, login as cruise and go to added a new profile in the settings.xml (if not exists) under the directory ~/.m2

<profile>
<id>profile-id-internal-repo</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>central</id>
<url>http://buildix.hostname/artifactory/repo</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>snapshots</id>
<url>http://buildix.hostname/artifactory/repo</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://buildix.hostname/artifactory/repo</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>snapshots</id>
<url>http://buildix.hostname/artifactory/repo</url>
<releases>
<enabled>false</enabled>
</releases>
</pluginRepository>
</pluginRepositories>
</profile>


That's it!! You may now go to http://buildix.hostname/artifactory and verfiy it by login as admin/password.

Buildix + Maven2 Part 2

Buildix uses ant by default, therefore, we need to install maven into the build server.
Follows the instructions in maven website to install maven to /usr/share/maven-2.0.7

Added $M2_HOME in /etc/profile
M2_HOME=/usr/share/maven-2.0.7
PATH="$PATH:$M2_HOME/bin"

make sure mvn -version is working and you would be ready to go!!

If you have a lot of projects and a very large scale project, we may need to increase cruise control heap sizes by modifying the following:
/usr/share/cruisecontrol/bin/cruisecontrol.sh

By default, if you create a new project using the "create_project" script, it will update the cruisecontrol.xml with Ant configuration. For maven2, we need to change the template from ant to maven.

Replace /usr/local/buildix/lib/cruisecontrol.fragment with the following codes:
<project name="@MY_PROJECT@" buildafterfailed="false">

<labelincrementer defaultLabel="${project.name}-1" separator="-"/>

<listeners>
<currentbuildstatuslistener file="/var/spool/cruisecontrol/logs/@MY_PROJECT@/currentbuildstatus.txt"/>
</listeners>

<modificationset quietperiod="30">
<svn RepositoryLocation="http://localhost/svn/@MY_PROJECT@/trunk/@MY_PROJECT@" username="cruise" password="cruise" />
</modificationset>

<bootstrappers>
<svnbootstrapper localWorkingCopy="/var/spool/cruisecontrol/tools"/>
<svnbootstrapper localWorkingCopy="/var/spool/cruisecontrol/@MY_PROJECT@" />
</bootstrappers>

<schedule interval="60">
<maven2 mvnscript="/usr/share/maven-2.0.7/bin/mvn" pomfile="/var/spool/cruisecontrol/@MY_PROJECT@/pom.xml" goal="clean install deploy" />
</schedule>

<log dir="logs/@MY_PROJECT@">
<merge dir="@MY_PROJECT@/target/surefire-reports" />
</log>

<publishers>
<onfailure>
<email mailhost="192.168.X.X" buildresultsurl="http://buildix_hostname/cruisecontrol/buildresults/@MY_PROJECT@?tab=buildResults" returnaddress="DevelopmentTeam@host.com">
<always address="DevelopmentTeam@host.com" />
</email>
</onfailure>
</publishers>

</project>
</cruisecontrol>

you are now ready to create a maven2 project in Buildix

Wednesday, October 17, 2007

IS250X


I've traded in my Euro with a brand new Lexus IS250X last week.

Euro is an excellent car with its price, however, I would like some a bit more luxury.

My new car is in black and it comes with 18" alloy wheel.

The car is very easy to handle, isolation is good. Although I think the car will be better with more torque, it's still an excellent car, really pleasure to drive with.

The car that parks itself

This is really impressive

http://www.news.com.au/dailytelegraph/story/0,22049,22596564-5006009,00.html

Wednesday, August 29, 2007

Buildix + Maven2

I've been spending a few days working with Buildix (cruise control, subversion) and maven2 recently. I would like to share my experiences with them here.

First at all, I have installed VMWare server (free for dev use) into one of the Dev Box in my company (yes, my company is a windows-based company). I downloaded the Buildix VMWare images and installed it into the VMWare server. Everything is pretty straight forward.

If you have install knoppix on your HD, the default locale in Buildix is UK, unless you live there, otherwise you need to change the locale.

look for lang=uk in the file /etc/lilo.conf

Knoppix will use DHCP to acquire the IP address for your sever, if you don't want to use dhcp, use netcardconfig, ifup/ifdown doesn't work for some reason.

(made sure you can connect to the internet because maven2 requires to download some libraries from the public repo)

One more thing ... If you are running VMWare, you will notice system time is lagging about 30s per min. In order to fix this, you need to edit the file /boot/grub/menu.lst and search for the line kernal. Add parameters clock=pit nosmp noapic nolapic.

To Be Continued.......