Archive for the ‘java’ Category

Subscribe to this blog via SMS!

Friday, January 4th, 2008

My little holiday project was to write a very simple wordpress plugin that allows people to get SMS notifications, along with “mobile web links”, whenever a wordpress blog is updated. I just tried it on my own blog and it worked like a charm:

1. You can subscribe to my blog feed by entering your phone number below. Or, you can text in word yuan to short number 41411 to subscribe.

2. When I post a new blog entry, you will get a SMS message on your phone with a link to the post, which you can open directly on your phone’s web browser (if you have a mobile data plan, as all iphone users, all blackberry users, and many smartphone users do)

That is it! Have fun guys! In the next post (probably on Monday), I will release the wordpress plugin and explain how to use it. Stay tuned! (Actually, subscribe now so that you do not miss my next post! ;))

Here is how the service works on a real phone:

1. Get a SMS link when the blog is updated

Screenshot0092.jpg

2. Open the link in the SMS

Screenshot0093.jpg Screenshot0094.jpg

3. See the page in action on the phone!

Screenshot0095.jpg Screenshot0096.jpg

Courtesy to Textmarks for providing the SMS services (including the short number 41411), and Mowser for providing transcoding services to re-format my blog pages for better display on small phone screens.

PS. This service only works on US phone numbers. Sorry guys, but if you find an equivalent to textmarks in Europe or Asia, please please let me know! Thanks.

Opera Mini 4 rocks

Tuesday, December 11th, 2007

Opera Mini 4 is a web browser for mobile phones. I have been using it for a couple of days now, and in terms of usability, Opera Mini beats the Webkit-based browser on my Nokia N80 — It is a “desktop fidelity” browser that delivers “iphone-like” user experience. (Actually, the iphone browser itself is webkit-based too.) And the best of all: Opera Mini is a Java ME application (with a significant server side component). It is one of the most polished Java ME applications I had used.

A “desktop fidelity” browser renders web pages just as they are — there is no attempt to “re-format” a wide web page into a single column (or into WML markup) for mobile display. Reformatting web pages to mobile often renders the page un-readable since the transcoder is not intelligent enough to distinguish important content from the noise (e.g., the ads and long navigation menus etc.) So, a “desktop fidelity” mobile browser first displays the entire width of a web page as a thumbnail on the screen. You can still scroll vertically as you would do in a desktop browser. Here is how the New York Times home page looks like in the Opera Mini 4 browser:

Picture 11.png

Picture 19.png

Notice that there is a small box that you can move around on the page. When you clicks on the keypad, the display zooms into the box and you can now view the page content, click on the links etc. Once roomed in, you can also scroll around to see the rest of the page, and/or zoom out to see the page overview.

Picture 17.png

Picture 18.png

Of course, the “zoom and view” idea itself is not new. The webkit browser shipped with my Nokia N80 can do this almost one year before the Apple iphone. What make the Opera Mini rock are the implementation details:

* Opera Mini 4 supports the landscape mode as you can see from the above screen shots. That is a huge plus for “zoom and view” browsing since it minimizes the “un-natural” horizontal scrolling when you are zoomed in.

* Opera Mini 4 is backed by a proxy server. When you request a web page, the proxy server goes out to fetch the page first, and it resizes all images before sending them to the phone. That not only makes those images display better on the phone screen, but also saves preciously bandwidth and reduces page load time.

* Opera Mini 4 runs CSS and JavaScript very well. Google ads, ajax data fields, complex CSS-based designs all show up very well in the browser. That is pretty crucial for accessing web 2.0 sites.

* Opera Mini 4 provides an intuitive and very configurable set of keypad shortcuts to access core features and your own bookmarks (it is called “speed dial”). Just dial *1 and watch your favorite web site come up. Very useful for the phone.

* Opera Mini 4 has a very good bookmaking system. You can easily go back and forward in your browsing history and bookmark any page you have accessed. You can even share bookmarks with your Opera browser on the PC.

* Opera Mini 4 provides the iphone-like “slide-out” visual effects when the web page changes. This is a small feature but makes the browser pleasant to use.

All in all, Opera Mini 4 is a very solid mobile browser. Its “desktop fidelity” browsing is a significant improvement over Opera Mini 3, which mostly reformat web pages to a single column mobile page. Having used many Java ME applications and wrote a couple of my own, I am very impressed by the quality of overall user experience delivered by Opera Mini 4. Try it out on your Java phone!

Seam book examples updated to Seam 2.0.0.GA

Tuesday, November 13th, 2007

As a service to my readers, I have updated all examples in my JBoss Seam book to Seam 2.0.0.GA.

Go download the zip file here

The example applications are fully tested against JBoss AS 4.2.0 GA.

NOTE: To build the examples, you now need to download and unzip Seam 2.0.0.GA first, and then set the build.properties file to point to the Seam installation directory.

Running Seam on non-JBoss Application Servers

Wednesday, November 7th, 2007

UPDATE: Several people commented that Seam works just fine with the TopLink JPA provider. I stand corrected. Thanks guys.

Here is what I posted to TSS today …

First, we try very hard to make Seam as generic as possible — so it would not require JBoss AS to run. The proof of this effort is that Seam runs on plain Tomcat (using RESOURCE_LOCAL transactions). So, in theory, it should run on all application servers out there. However, since all Seam developers use JBoss AS on a daily basis (we happen to believe that JBoss AS is the best AS out there :)), it is natural that Seam is tested most extensively on JBoss AS. Also, as an open source project, we do not have access to commercial WLS, WAS, ORA licenses, and do not have access to their support. So, our testing on those servers is not very comprehensive. I have personally installed the trial versions of those servers multiple times since they expire all the time. It is extremely time consuming …

So, the testing on commercial app servers is not very good at this moment. If you encounter issues with non-JBoss servers, raising them on the Seam forum is your best bet. Now here is a breakdown of what works and what not (to the best of my knowledge).

* Tomcat 5.5 and 6: Seam applications work out of the box on those servers if you use the RESOURCE_LOCAL transaction (see examples/jpa). You can use EJB3 features if you install JBoss Embeddable on top of Tomcat.

* Glassfish: Glassfish v2 is known to work with Seam (see examples/jee5 for an example). But we strongly recommend you use Hibernate as the JPA provider — not the default TopLink.

* Oracle: Oracle 10 is known to work with Seam (see examples/jee5 and examples/jpa). Again, choose Hibernate as the JPA provider.

* WebLogic: WebLogic 9.2 and 10 can be made to work with JPA + JTA transaction (see examples/jpa). However, EJB3 on WLS 10 does not yet work. There is a reflection error from the EJB proxy the last time I checked.

* WebSphere: I think the examples/jpa can work against WAS 6.1.0.9. You do need to tweak stuff a lot to make JSF 1.2 and Facelets work on that server. We have not tried WebSphere EJB3. However, anything beyond a simple CRUD app might have problems on WAS. One of the reasons is that the IBM JVM5 has a bug that complains about unknown annotations (the correct way is to ignore unknown annotations as the Sun JVM does). Unless IBM fixes this, you will have problems running Seam on WAS.

So, that’s it. If any of you can help us testing this stuff, please let us know! :)

Slides for Seam talk at the New England JUG

Wednesday, October 24th, 2007

I gave a 2-hour talk on JBoss Seam in the New England Java User’s Group last Thursday. Although the talk was at the same night as a crucial game for Red Sox, it still managed to attract 250+ people — making it one of largest JUG meetings I have ever attended! I had a great time there, and learned first hand about how Java developers in the Boston area are using JBoss Seam to solve real world problems. For those who are interested, the presentation itself can be found here:

Slides for the JBoss Seam presentation in NEJUG, Oct 18th 2007

I enjoyed a “re-union” with my Red Hat colleagues in the Boston area: Shelly McGowan, Chantal Yang, Bill Burke, Kurt Stam, and Rajesh Rajasekaran. Thank you guys for making the meeting a success! In addition, I’d also like to thank Mark Johnson (the president of the NEJUG), Heather Fox (publicist at Prentice Hall), and Shaun Connolly (my sponsor at Red Hat) for organizing everything!

Finally, a couple of references to things I mentioned in the meeting:

Nominate your products / projects for the 18th Jolts Award

Tuesday, October 23rd, 2007

Dr Dobb’s Journal’s Jolt award is one of the longest running and most prestigious awards in the software industry. The 18th Jolt Award is now open for nominations:

http://www.joltnominations.com/Jolt/

Hint: If you develop tools for mobile applications, Jolt does have a category for mobile tools. I will participate in this category heavily this year.

To be qualified for Jolts, you have to submit your own product — there is a small submission fee ($50 for open source projects) to cover admin costs. As a Jolt judge for the past several years, I can tell you that none of the judges is paid. We are all volunteers contributing our time for free to go through the complicated software evaluation process. What do we get out of it? Well, we get exposure to the latest happenings in the industry and get to put “Jolts Judge” on our name cards. ;)

What do you get out of it? Well, if your product wins Jolts, that gives you some major bragging right! Even if your product does not win, by participating in the process, you get Jolt judges (most of them are consultants influencing purchasing decisions) to look carefully at your product. If some of the judges like your product, they might blog about it or recommend it in their consulting work.

In the past several years, we got an overwhelming number of submissions every year. It is nearly impossible to evaluate each of them in detail, if the judges are not already using the product in his/her daily work. So, it will be enormously helpful if you can prepare a flash or live demo of your product to illustrate the key features that differentiates your product from the rest.

JBoss Seam project setup with Maven — Part 2: EAR deployment

Tuesday, October 9th, 2007

In a previous post, I discussed how to setup a Maven project for your Seam WAR application. However, most Seam developers are probably working on applications with EJB3 components to fully take advantage of the service infrastructure of the JBoss AS container. So, to complete this series, I setup a maven project for Seam EAR deployment. The project structure is as follows. The ejb module builds the JAR for EJB3 components; the war project build the web application; and the ear module builds the EAR application with necessary library JARs.

CODE:
  1. .
  2.  |-- pom.xml
  3.  |
  4.  |-- ear
  5.  |   `-- pom.xml
  6.  |
  7.  |-- ejb
  8.  |   |-- pom.xml
  9.  |   |-- src
  10.  |       `-- main
  11.  |           |-- java
  12.  |           |    `-- com
  13.  |           |         `-- example
  14.  |           |               `-- ejb
  15.  |           |                    |-- MyEnterpriseBeanImpl.java
  16.  |           |                    `-- MyEnterpriseBean.java
  17.  |            `-- resources
  18.  |                |-- seam.properties
  19.  |                 `--  ejb-jar.xml
  20.  |
  21.  |-- war
  22.       |-- pom.xml
  23.        `-- src
  24.             `-- main
  25.                  |-- java
  26.                  |   `-- com
  27.                  |       `-- example
  28.                  |             `-- SampleAction.java (and other Java source files)
  29.                  |-- resources
  30.                  |   |-- META-INF
  31.                  |   |   `-- persistence.xml
  32.                  |   |-- messages.properties
  33.                  |   `-- seam.properties
  34.                  `-- webapp
  35.                      |-- WEB-INF
  36.                      |    | -- components.xml
  37.                      |    | -- pages.xml
  38.                      |    | -- face-config.xml
  39.                      |     `-- web.xml
  40.                      `-- hello.xhtml (and other web content, CSS, templates, and images)

The main pom.xml file defines the shared libraries required by all modules. It optionally uses the Seam parent POM to set the version numbers for the dependency JARs. Here is how it might look like:

XML:
  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  2.  
  3.   <repositories>
  4.     <repository>
  5.       <id>jboss-snapshot</id>
  6.       <name>The JBoss maven repo</name>
  7.       <url>http://snapshots.jboss.org/maven2</url>
  8.     </repository>
  9.   </repositories>
  10.   <parent>
  11.     <groupId>org.jboss.seam</groupId>
  12.     <artifactId>root</artifactId>
  13.     <version>2.0.0-SNAPSHOT</version>
  14.   </parent>
  15.  
  16.   <modelVersion>4.0.0</modelVersion>
  17.   <groupId>mystuff</groupId>
  18.   <artifactId>mystuff</artifactId>
  19.   <packaging>pom</packaging>
  20.   <version>1.0</version>
  21.   <name>mystuff</name>
  22.   <url>http://maven.apache.org</url>
  23.  
  24.   <dependencies>
  25.  
  26.     <dependency>
  27.       <groupId>log4j</groupId>
  28.       <artifactId>log4j</artifactId>
  29.       <scope>provided</scope>
  30.     </dependency>
  31.  
  32.     <dependency>
  33.       <groupId>junit</groupId>
  34.       <artifactId>junit</artifactId>
  35.       <scope>test</scope>
  36.     </dependency>
  37.  
  38.   </dependencies>
  39.  
  40.   <modules>
  41.     <module>ejb</module>
  42.     <module>war</module>
  43.     <module>ear</module>
  44.   </modules>
  45.  
  46.   <build>
  47.     <plugins>
  48.       <plugin>
  49.         <groupId>org.apache.maven.plugins</groupId>
  50.         <artifactId>maven-compiler-plugin</artifactId>
  51.         <configuration>
  52.           <source>1.5</source>
  53.           <target>1.5</target>
  54.         </configuration>
  55.       </plugin>
  56.     </plugins>
  57.   </build>
  58. </project>

The ejb/pom.xml file defines the dependencies for the EJB3 module. Everything here is in the provided scope -- unless testing-specific libraries, which are in the test scope.

XML:
  1. <project>
  2.  
  3.   <parent>
  4.     <artifactId>mystuff</artifactId>
  5.     <groupId>mystuff</groupId>
  6.     <version>1.0</version>
  7.   </parent>
  8.  
  9.   <modelVersion>4.0.0</modelVersion>
  10.   <groupId>mystuff</groupId>
  11.   <artifactId>ejb</artifactId>
  12.   <name>mystuff - ejb</name>
  13.   <version>1.0</version>
  14.   <url>http://maven.apache.org</url>
  15.  
  16.   <build>
  17.     <finalName>ejb</finalName>
  18.   </build>
  19.  
  20.   <dependencies>
  21.  
  22.     <dependency>
  23.       <groupId>org.hibernate</groupId>
  24.       <artifactId>hibernate</artifactId>
  25.       <scope>provided</scope>
  26.     </dependency>   
  27.  
  28.     <dependency>
  29.       <groupId>org.hibernate</groupId>
  30.       <artifactId>hibernate-entitymanager</artifactId>
  31.       <scope>provided</scope>
  32.     </dependency>
  33.  
  34.     <dependency>
  35.       <groupId>org.hibernate</groupId>
  36.       <artifactId>hibernate-annotations</artifactId>
  37.       <scope>provided</scope>
  38.     </dependency>
  39.  
  40.     <dependency>
  41.       <groupId>org.hibernate</groupId>
  42.       <artifactId>hibernate-validator</artifactId>
  43.       <scope>provided</scope>
  44.     </dependency>
  45.  
  46.     <dependency>
  47.       <groupId>org.jboss.seam</groupId>
  48.       <artifactId>jboss-seam</artifactId>
  49.       <scope>provided</scope>
  50.     </dependency>
  51.  
  52.     <dependency>
  53.       <groupId>javax.ejb</groupId>
  54.       <artifactId>ejb-api</artifactId>
  55.       <scope>provided</scope>
  56.     </dependency>
  57.  
  58.     <dependency>
  59.       <groupId>hsqldb</groupId>
  60.       <artifactId>hsqldb</artifactId>
  61.       <version>1.7.2</version>
  62.       <scope>test</scope>
  63.     </dependency>
  64.  
  65.   </dependencies>
  66.  
  67. </project>

The war/pom.xml file defines the dependencies for the WAR module. It depends on the ejb module.

XML:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project>
  3.   <parent>
  4.     <artifactId>mystuff</artifactId>
  5.     <groupId>mystuff</groupId>
  6.     <version>1.0</version>
  7.   </parent>
  8.   <modelVersion>4.0.0</modelVersion>
  9.  
  10.   <groupId>mystuff</groupId>
  11.   <artifactId>war</artifactId>
  12.   <name>mystuff - web</name>
  13.   <version>1.0</version>
  14.   <packaging>war</packaging>
  15.   <url>http://maven.apache.org</url>
  16.  
  17.   <build>
  18.     <finalName>war</finalName>
  19.   </build>
  20.  
  21.   <dependencies>
  22.  
  23.     <dependency>
  24.       <groupId>mystuff</groupId>
  25.       <artifactId>ejb</artifactId>
  26.       <version>1.0</version>
  27.       <scope>provided</scope>
  28.       <type>ejb</type>
  29.     </dependency>
  30.  
  31.    <!-- The following 4 dependencies are included in the WEB-INF/lib of the war -->
  32.  
  33.     <dependency>
  34.       <groupId>org.jboss.seam</groupId>
  35.       <artifactId>jboss-seam-ui</artifactId>
  36.     </dependency>
  37.  
  38.     <dependency>
  39.       <groupId>org.jboss.seam</groupId>
  40.       <artifactId>jboss-seam-debug</artifactId>
  41.     </dependency>
  42.  
  43.     <dependency>
  44.       <groupId>com.sun.facelets</groupId>
  45.       <artifactId>jsf-facelets</artifactId>
  46.     </dependency>
  47.  
  48.     <dependency>
  49.       <groupId>org.richfaces.ui</groupId>
  50.       <artifactId>richfaces-ui</artifactId>
  51.     </dependency>
  52.  
  53.     <!-- The "provided" dependencies are only need for compilation -->
  54.  
  55.     <dependency>
  56.       <groupId>javax.servlet</groupId>
  57.       <artifactId>servlet-api</artifactId>
  58.       <scope>provided</scope>
  59.     </dependency>
  60.  
  61.     <dependency>
  62.       <groupId>org.jboss.seam</groupId>
  63.       <artifactId>jboss-seam</artifactId>
  64.       <scope>provided</scope>
  65.     </dependency>
  66.  
  67.     <dependency>
  68.       <groupId>javax.faces</groupId>
  69.       <artifactId>jsf-api</artifactId>
  70.       <scope>provided</scope>
  71.     </dependency>
  72.  
  73.     <dependency>
  74.       <groupId>javax.faces</groupId>
  75.       <artifactId>jsf-impl</artifactId>
  76.       <scope>provided</scope>
  77.     </dependency>
  78.  
  79.     <dependency>
  80.       <groupId>org.hibernate</groupId>
  81.       <artifactId>hibernate-validator</artifactId>
  82.       <scope>provided</scope>
  83.     </dependency>
  84.  
  85.   </dependencies>
  86. </project>

The ear/pom.xml file defines how the EAR application is assembled. You need to declare any JARs you want to include in the EAR as dependencies. I also used a JBoss-specific element to setup the class loader repository for the application. It is often needed in JPA applications. Yes, it is verbose -- if you have a better idea, let me know. :)

XML:
  1. <project>
  2.  
  3.   <parent>
  4.     <artifactId>mystuff</artifactId>
  5.     <groupId>mystuff</groupId>
  6.     <version>1.0</version>
  7.   </parent>
  8.  
  9.   <modelVersion>4.0.0</modelVersion>
  10.   <groupId>mystuff</groupId>
  11.   <artifactId>ear</artifactId>
  12.   <name>mystuff - ear</name>
  13.   <packaging>ear</packaging>
  14.   <version>1.0</version>
  15.   <url>http://maven.apache.org</url>
  16.  
  17.   <dependencies>
  18.  
  19.     <dependency>
  20.       <groupId>mystuff</groupId>
  21.       <artifactId>ejb</artifactId>
  22.       <version>1.0</version>
  23.       <type>ejb</type>
  24.     </dependency>
  25.  
  26.     <dependency>
  27.       <groupId>mystuff</groupId>
  28.       <artifactId>war</artifactId>
  29.       <version>1.0</version>
  30.       <type>war</type>
  31.     </dependency>
  32.  
  33.     <dependency>
  34.       <groupId>org.jboss.seam</groupId>
  35.       <artifactId>jboss-seam</artifactId>
  36.       <type>ejb</type>
  37.     </dependency>
  38.  
  39.     <dependency>
  40.       <groupId>org.jboss.seam</groupId>
  41.       <artifactId>jboss-el</artifactId>
  42.       <exclusions>
  43.         <exclusion>
  44.           <groupId>javax.el</groupId>
  45.           <artifactId>el-api</artifactId>
  46.         </exclusion>
  47.       </exclusions>
  48.       <type>jar</type>
  49.     </dependency>
  50.  
  51.     <dependency>
  52.       <groupId>commons-beanutils</groupId>
  53.       <artifactId>commons-beanutils</artifactId>
  54.       <exclusions>
  55.         <exclusion>
  56.           <groupId>commons-logging</groupId>
  57.           <artifactId>commons-logging</artifactId>
  58.         </exclusion>
  59.       </exclusions>
  60.       <type>jar</type>
  61.     </dependency>
  62.  
  63.   </dependencies>
  64.  
  65.   <build>
  66.     <plugins>
  67.       <plugin>
  68.         <groupId>org.apache.maven.plugins</groupId>
  69.         <artifactId>maven-ear-plugin</artifactId>
  70.         <configuration>
  71.           <jboss>
  72.             <version>4</version>
  73.             <loader-repository>mystuff:loader=mystuff.ear</loader-repository>
  74.           </jboss>
  75.  
  76.           <modules>
  77.             <webModule>
  78.               <groupId>mystuff</groupId>
  79.               <artifactId>war</artifactId>
  80.               <contextRoot>mystuff</contextRoot>
  81.             </webModule>
  82.  
  83.             <ejbModule>
  84.               <groupId>mystuff</groupId>
  85.               <artifactId>ejb</artifactId>
  86.             </ejbModule>
  87.  
  88.             <ejbModule>
  89.               <groupId>org.jboss.seam</groupId>
  90.               <artifactId>jboss-seam</artifactId>
  91.             </ejbModule>
  92.  
  93.             <!-- The stuff that needs to go in the lib directory.
  94.                  They will not be included in application.xml -->
  95.  
  96.             <jarModule>
  97.               <groupId>org.jboss.seam</groupId>
  98.               <artifactId>jboss-el</artifactId>
  99.               <bundleDir>lib</bundleDir>
  100.             </jarModule>
  101.  
  102.             <jarModule>
  103.               <groupId>commons-beanutils</groupId>
  104.               <artifactId>commons-beanutils</artifactId>
  105.               <bundleDir>lib</bundleDir>
  106.             </jarModule>
  107.  
  108.           </modules>
  109.         </configuration>
  110.       </plugin>
  111.     </plugins>
  112.   </build>
  113.  
  114. </project>

JBoss Seam project setup with Maven — Part 1: WAR deployment

Tuesday, October 2nd, 2007

Pete Muir recently posted that Seam 2.0 will support Maven integration. It is perfect timing for me since I have just started to use Maven in my new projects. So, I went through the exercise to setup simple Seam web projects in Maven. It is really quite easy. The project builds a single WAR for deployment (you can only use Seam POJO in the WAR -- no EJBs). You can configure it to generate WAR for JBoss AS or Tomcat 6. The beauty of using Maven is that you do not need to worry about things like finding the right version of JARs, setting up the project structure, managing build script etc. In fact, there is no build script to write. So, here is the structure of the source project.

CODE:
  1. .
  2.  |-- pom.xml
  3.  `-- src
  4.      `-- main
  5.          |-- java
  6.          |   `-- com
  7.          |       `-- example
  8.          |             `-- SampleAction.java (and other Java source files)
  9.          |-- resources
  10.          |   |-- META-INF
  11.          |   |   `-- persistence.xml
  12.          |   `-- seam.properties
  13.          `-- webapp
  14.              |-- WEB-INF
  15.              |    | -- components.xml
  16.              |    | -- pages.xml
  17.              |    | -- face-config.xml
  18.              |     `-- web.xml
  19.              `-- hello.xhtml (and other web content, CSS, templates, and images)

As you can see, you put your application code and configuration in the following directories.

  • All the Java source code (e.g., entity beans, Seam POJOs) go into src/main/java.
  • All Seam and web-related configuration files go into src/main/webapp/WEB-INF.
  • The JPA configuration goes into resources/META-INF/persistence.xml.
  • All web content goes into src/main/webapp.
  • The resources/seam.properties file is an empty file. It is require for Seam to scan annotations in this WAR

The dependency JARs are declared in the pom.xml file. Below is the pom.xml I used to generate a WAR for JBoss AS deployment. A couple of things to notice here:

  • I set the Seam official POM as my "parent" so that I can let Seam figure out the correct versions of the dependency JARs. Notice that I do not need to specify the Facelets JAR version in my POM. Seam will choose a compatible version for me.
  • The compiler setting must be "1.5" so that it can handle annotations.
  • The javax.el.el-api jar needs to be in the provided scope as it conflicts with the one already in JBoss and Tomcat 6.

That's it. Here is the pom.xml.

XML:
  1. <project xmlns="http://maven.apache.org/POM/4.0.0"
  2.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  4.  
  5.   <repositories>
  6.     <repository>
  7.       <id>jboss-snapshot</id>
  8.       <name>The JBoss maven repo</name>
  9.       <url>http://snapshots.jboss.org/maven2</url>
  10.     </repository>
  11.   </repositories>
  12.  
  13.   <parent>
  14.     <groupId>org.jboss.seam</groupId>
  15.     <artifactId>root</artifactId>
  16.     <version>2.0.0-SNAPSHOT</version>
  17.   </parent>
  18.  
  19.   <modelVersion>4.0.0</modelVersion>
  20.  
  21.   <groupId>mytest</groupId>
  22.   <artifactId>seam-maven</artifactId>
  23.   <name>helloworld</name>
  24.   <version>1.0</version>
  25.   <packaging>war</packaging>
  26.   <url>http://maven.apache.org</url>
  27.  
  28.   <build>
  29.     <finalName>helloworld</finalName>
  30.     <plugins>
  31.       <plugin>
  32.         <groupId>org.apache.maven.plugins</groupId>
  33.         <artifactId>maven-compiler-plugin</artifactId>
  34.         <configuration>
  35.           <source>1.5</source>
  36.           <target>1.5</target>
  37.         </configuration>
  38.       </plugin>
  39.     </plugins>
  40.   </build>
  41.  
  42.   <dependencies>
  43.  
  44.     <dependency>
  45.       <groupId>org.jboss.seam</groupId>
  46.       <artifactId>jboss-seam</artifactId>
  47.     </dependency>
  48.  
  49.     <dependency>
  50.       <groupId>org.jboss.seam</groupId>
  51.       <artifactId>jboss-el</artifactId>
  52.       <exclusions>
  53.         <exclusion>
  54.           <groupId>javax.el</groupId>
  55.           <artifactId>el-api</artifactId>
  56.         </exclusion>
  57.       </exclusions>
  58.     </dependency>
  59.  
  60.     <dependency>
  61.       <groupId>org.jboss.seam</groupId>
  62.       <artifactId>jboss-seam-ui</artifactId>
  63.     </dependency>
  64.  
  65.     <dependency>
  66.       <groupId>com.sun.facelets</groupId>
  67.       <artifactId>jsf-facelets</artifactId>
  68.     </dependency>
  69.  
  70.   </dependencies>
  71.  
  72. </project>

Now, what if I want the WAR to be deployed in plain Tomcat 6? No problem, just add the JSF and Hibernate dependencies as follows. There is no need to meddle with commons jars and other 3rd party JARs since JSF and Hibernate dependencies automatically resolve them! Of course, plain Tomcat 6 does not provide a JTA transaction manager, so you will need to provide your own or use RESOURCE_LOCAL transaction -- but you should already knew that if you choose Tomcat ...

XML:
  1. <!-- The following dependencies are needed for Tomcat 6 deployment -->
  2.  
  3.     <dependency>
  4.       <groupId>javax.faces</groupId>
  5.       <artifactId>jsf-api</artifactId>
  6.     </dependency>
  7.  
  8.     <dependency>
  9.       <groupId>javax.faces</groupId>
  10.       <artifactId>jsf-impl</artifactId>
  11.     </dependency>
  12.  
  13.     <dependency>
  14.       <groupId>org.hibernate</groupId>
  15.       <artifactId>hibernate</artifactId>
  16.     </dependency>
  17.  
  18.     <dependency>
  19.       <groupId>org.hibernate</groupId>
  20.       <artifactId>hibernate-validator</artifactId>
  21.     </dependency>
  22.  
  23.     <dependency>
  24.       <groupId>org.hibernate</groupId>
  25.       <artifactId>hibernate-annotation</artifactId>
  26.     </dependency>
  27.  
  28.     <dependency>
  29.       <groupId>org.hibernate</groupId>
  30.       <artifactId>hibernate-entitymanager</artifactId>
  31.     </dependency>

So, go and have fun with Maven now! Let me know if there is any issues!

My personal tipping point for Maven

Monday, October 1st, 2007

I have always resisted using anything other than ANT to build my Java projects. I mean, if ANT can do the job and everyone else already has it, why do I need to learn anything else, right? However, Maven2 has finally reached the tipping point for me last week.

First, the Seam team has officially made Seam builds with all its dependencies available from a Maven repository. Seam has been using Maven to manage its own builds for quite sometime now. But the new Maven support makes it easy for developers to set up Seam application projects in Maven -- it is now quite easy to make sure that all 3rd party JARs you use in your application are the ones tested by the Seam team.

Second, Netbeans 6.0 released a beta, which boasts Maven project support. You can now open Maven project directories directly in Netbeans, and have all the source/resources/test packages listed in the project browser with all the correct classpaths. Okay, you still need to install the Mavenide plugin. As a long time Netbeans user, I found it reassuring to see that the Netbeans team is committed to bring first class Maven support to the IDE.

Last and most important, the R&D team at eZee has decided to use Maven to manage our internal projects. The rationale is that since we are starting brand new projects, we are not chained to legacy ANT scripts. We have an opportunity to start fresh from Maven. Why not try it? Even if Maven does not work out, we still have an opportunity to convert the projects to ANT -- but we will all learn a lot of the exercise.

So, how do I like Maven after a week of using it in real life? I have to say that I really liked it. Maven takes a very structured approach to build management. It is not as flexible as ANT. For most "standard" project types, Maven just supports them out of the box -- there is no build script to write -- just put your code and configuration files in the right default directories and you are ready to go. Speaking of "configuration by convention!" However, if you want to do anything not supported by default, you have to write code to plug into pre-defined integration points in Maven.

Maven really reminds me a lot about JSF -- it does not allow you to do random scriptlets like JSP, but it provides integration points where you can heavily customize the behavior of the system. Sure, it is more work to create code that conforms to the "framework". But you also get more stability and maintainability out of it. I am hoping that Maven can allow me to achieve the same!

JSF and Mobile Web Applications — Part 2: The ServletFilter approach

Wednesday, September 26th, 2007

The challenges to develop a mobile web application are two-folds:

  1. The application needs to generate different page layout and markups for different devices. This is not just about using wider layout for wider screens -- it also includes using table / CSS / JavaScript for devices that support those features.
  2. The content (e.g., image, media, and text) also need to be customized and transformed for each device.

The web server can tell the client device type from the user agent header in the incoming HTTP request. The question now is how we integrate the user agent header information into the web framework and generate the right web page. The JSF renderkit approach we discussed earlier is not practical since we are not going to go through the trouble to write our own JSF renderkit.

One potential choice is to use the WURFL WALL JSP tag library, which can generate WML / CHTML / XHTML MP markups from the same JSP page based on the user agent. But the WALL tag library is difficult to integrate with modern web frameworks: it requires you to construct your page in WALL tags completely, while frameworks like JSF requires you to use its own component tags on the page. The WALL tag library also only deal with markup transformation. It does not provide different page layouts for different devices / screen sizes (except for the most basic customization hardcoded into the tag library), and does not deal with content transformation / management. We need a more flexible solution.

Don Kittle and Frank Carver mentioned in the comments to my previous blog entry that they use a JSTL servlet filter to transform the rendered XHTML content into WML / XHTML MP, and use special markups on the view template to progressively select content fragments for the target device. Those solutions are very good but they generally break the JSF component model, and to me, they are not generic enough.

So, here is what I think we could do (please let me know if I am missing something!): We can use a URL re-writing servlet filter to check the user agent of the incoming request, figure out the device attributes (e.g., screen sizes, whether CSS is supported etc.), and dispatch the request to the correct template for rendering based on the device attributes. For instance, a request from Nokia 6600 will be dispatched to the 176x208 XHTML MP with CSS template. For most current mobile device, I think the following 10 templates (in 5 groups) will suffice:

* Basic XHTML MP without CSS or table for small screens (width <= 128)
* Basic XHTML MP without CSS or table for medium screens (128 < width <= 176)

* Basic XHTML with table support for small screens (width < 128)
* Basic XHTML with table support for medium screens (128 < width <= 176)

* XHTML MP with CSS for small screens (width <= 128)
* XHTML MP with CSS for medium screens (128 < width <= 176)
* XHTML MP with CSS for large screens (176 < width <= 320, i.e., iphone-like)

* XHTML MP with CSS and JavaScript for medium screens (128 < width <= 176)
* XHTML MP with CSS and JavaScript for large screens (176 < width <= 320, i.e., iphone-like)

* Regular full blown XHTML with JavaScript for PC screens

The filter also saves the device attribute in the HttpSession object. When backing beans render content for the page, they can use the device attributes from the session to retrieve the right content for the device. For instance, the backing bean would retrieve a 176x10 banner image for the Nokia 6600, and limit the dynamic text to less than 250 chars (more or less one screen).

In the context of JBoss Seam, it would be great if we can make the filter a Seam component so that the user can configure it (e.g., URL rewriting rules for template locations) in components.xml. We can also make the device attribute object available as a Seam component so that all JSF beans can inject it as needed. Maybe this will be my next contribution to Seam. :)

Now, there are some potential issues with this approach. Let me explain why they do not matter in most cases ...

  • There are some repetition to write different templates for the same content. But it improves the usability of both the mobile and PC web pages, and that is all that matters. Also, the clarity of XHTML MP/HTML/WML-based design is far better than the opaque JSF tag-based design.
  • The standard JSF renderer cannot generate WML markup for JSF input/form tags. That needs to be corrected by developing a set of WML-specific JSF form tags. That is much simpler than meddling with the renderkit. And frankly, there are not many WML devices out there! The vast majority of mobile phones today are XHTML MP-compliant and works perfectly with standard JSF tags.
  • Some JSF implementations (e.g., MyFaces) use JavaScript to trigger button click actions. That will not work on some lower end devices. Fortunately, JavaScript-free high-quality JSF implementations (e.g., the RI) are readily available.

All in all, I believe the servlet filter approach is the right way to go for most mobile web applications. It allows web pages to be optimized for a variety of devices from the PC to iphone to PDAs to small mobile phones. And it can be used in any web framework since there is really nothing specific to JSF here!

In the next post, I will discuss how to map user agent strings to device capabilities (e.g., supported markups and screen sizes) in the filter, as well as exactly how many different view templates you will need in a typical mobile web application.

JSF and Mobile Web Applications — Part 1: What looks good on paper doesn’t always work out

Tuesday, September 25th, 2007

Update: Please see Dan Allen's comment below for an alternative view. I do agree with him that component level multi-rendering makes sense. But without a good, production ready renderkit, all the practical problems listed in this blog post still exist. The bottom line is that we need a renderkit that can dynamically detect the device, dispatch to different page templates based on the device, render standard JSF components into multiple markups, and generate customized content for the device. That far exceeds the capability of any renderkit out there ...


One of the much touted benefits of JavaServer Faces (JSF) is its capability to render multiple outputs from the same view page. For instance, in theory, the same JSP page can be rendered into WML/CHTML/XHTML MP for mobile phone browsers and regular HTML for PC browsers. However, no one uses that in the real world for a couple of very good reasons. The static JSF renderkit for "mobile content" just does not cut it:

  1. The mobile phones and PCs have very different screen sizes and media capabilities. It would be silly to assume that you can use the same page layout and display the same type of contents for both use cases. If forced to do, the developer will just have to use the lowest common denominator and ruin the user experience. More than likely, you will need different view templates for phones and PCs. Hence the entire point of "reuse the view page" is moot.
  2. Even if it is possible to reuse the page, the price you pay is to write the page entirely in JSF tags. There must be no regular XHTML/HTML/WML tags in the page for this to work. That does not bode well with almost all web page authoring tools. The rendered page is opaque to page designers. As we have seen many times, web developers prefer to construct the page template primarily in "regular" markups and only use JSF tags for specific input / data components.
  3. Since the JSF renderkit is statically configured in faces-config.xml, you cannot have mobile web pages and regular PC web pages co-exist in the same web application. That is really silly and very limiting -- what is the point of page reuse if you have to deploy two web applications to serve those pages?
  4. While JSF can generate WML/XHTML tags from the same page, it does not address deeper content transformation issues. For instance, you will probably need to display different images on different devices based on the target screen size.
  5. Finally, probably because of the above, there is really no production quality mobile renderkit out there for JSF. MyFaces has a basic WML renderkit. But it is just for demo and has not been updated in a long time. There is no renderkit for XHTML MP.

One way to address issues #3 and #4 is to build some user agent detection logic into the renderkit. The renderkit figures out the device type of the incoming request and generate the right tag / image for it. For instance, the following user agent indicates that the request comes from a Nokia 6600.

Nokia6600/1.0 (5.27.0) SymbianOS/7.0s Series60/2.0
Profile/MIDP-2.0 Configuration/CLDC-1

This user agent causes the renderkit to generate XHTML MP tags with all images on the page resized to below 240 pixels wide. The down side, however, is that renderkits are pretty complex to develop and we still have not addressed issues #1 and #2.

In the next post later this week, I will propose a better solution to develop mobile web applications with JSF and potentially other web frameworks. Stay tuned!

Leaving Red Hat (and go back to mobile)

Monday, August 27th, 2007

Time flies. It has been 3 years since I joined JBoss in August 2004. In those 3 years, we went from the "bad boy of open source" to one of the most successful software companies since the dotcom era. We went through a 350-million-dollar acquisition by Red Hat and made a few millionaire open source developers in the process. We fought and won battles against industry mammoth like IBM, Oracle, and BEA with style and vengeance. It is a great pleasure to work with such a talented and passionate team of professionals. Yet, the time has came for me to move on. I will be leaving Red Hat by the end of this month to join an Austin-based startup, eZee Inc., to work on mobile payment applications.

Picture 26.png

As someone who wrote 3 books on mobile technologies, I always had a great passion for mobile. eZee has a very experienced management / business development team, leading technologists (pat on the back for myself!), strong connection with University of Texas, and adequate funding to push a consumer product. It is too good an opportunity for me to pass up ... Read more about the company here. My role in the new company will be "mobile strategist." What the hell is that, you ask? Well, as typical in a startup, I will do everything from product design, project management, writing code, to taking out the trash. :)

We have around 10 employees now and look to grow aggressively. If you are interested in joining us, let me know. I cannot promise the future but I can guarantee that you will be working on some of the most exciting technologies (server side and mobile client side) today. As technologists, we set out to change the world (i.e., to change the way how people use money). If we happen to make some money in the process, that would be very nice too. ;)

While the software we write in eZee will not be open source (financial and payment stuff are highly sensitive), we will certainly use a lot of open source products and contribute back to the community. So, I will continue to be an active committer on several JBoss / Red Hat open source projects, in particular JBoss Seam and JBoss Tools. I will continue my writing on JBoss Seam in this blog and plan to publish a second edition of my JBoss Seam book early next year.

Seam and SOA

Tuesday, July 31st, 2007

I am in Atlanta for our internal JBoss ESB / SOA training this week. Burr Sutter and his team are doing a great job conveying our SOA vision -- to mesh and reuse services you already built in your "single silo" applications (e.g., a web store and a warehouse management app can share an "order" object when the user confirms an order. Each application then process and save the order in their own ways.).

I have been thinking how Seam fits into this picture. With the support for web services in Seam 2.0, it is actually quite easy to fit a Seam application into a SOA environment. In this post, I'd like to discuss some work I did with the seambay example (a spoof auction site) to make it share its listings with other services, and receive listings from other services.

@Out

To make the seambay application share its auction listings with other services in the SOA environment, we need to serialize the Auction object and push it to the ESB, while it is being saved into the database by the Seam application. The least intrusive way to do this is to use an EJB3 interceptor to "steal" the Auction object when the confirm() method is called. This way, we do not need to make any change to the Seam application code.

JAVA:
  1. public class AuctionInterceptor {
  2.  
  3.   @AroundInvoke
  4.   public Object sendAuctionToESB (InvocationContext ctx) throws Exception {
  5.  
  6.     System.out.println("*** Entering AuctionInterceptor");
  7.  
  8.     Object target = ctx.getTarget ();
  9.     if (target instanceof AuctionAction) {
  10.       if (ctx.getMethod().getName().equals("confirm")) {
  11.         System.out.println("We will send the following Auction object to ESB");
  12.         Auction auction = ((AuctionAction) target).getAuction ();
  13.         // Send the following XML string to JMS
  14.         formatMessage(auction);
  15.       }
  16.     }
  17.  
  18.     try {
  19.       return ctx.proceed();
  20.     } finally {
  21.        System.out.println("*** Exiting AuctionInterceptor");
  22.     }
  23.   }
  24.   ... ...
  25. }

When the user enters a new auction listing on the site, the server console prints the following message.

Picture 18.png

@In

To make the Seam application as a SOA service end-point requires external applications to invoke its business logic through web services. The challenge here is that most business logic in Seam are managed in "conversations", which holds finer grained application state than Http sessions. How do you keep the conversation state across multiple SOAP calls? Well, here is where the Seam Web Service comes into play.

To expose business logic methods in Seam components as Web Service methods, you need to write a facade SLSB to wrap around the methods you want to expose. You can use the Seam.getComponent() method to get any Seam component by its name and then proceed to invoke any method on the component.

JAVA:
  1. @Stateless
  2. @WebService(name = "AuctionService", serviceName = "AuctionService")
  3. public class AuctionService implements AuctionServiceRemote
  4. {
  5.    @WebMethod
  6.    public boolean login(String username, String password)
  7.    {
  8.       Identity.instance().setUsername(username);
  9.       Identity.instance().setPassword(password);
  10.       Identity.instance().login();
  11.       return Identity.instance().isLoggedIn();
  12.    }
  13.  
  14.    @WebMethod
  15.    public void createAuction(String title, String description, int categoryId)
  16.    {
  17.       AuctionActionInt action = getAuctionAction();
  18.       action.createAuction();
  19.       action.setDetails(title, description, categoryId);
  20.    }
  21.  
  22.    @WebMethod
  23.    public Auction getNewAuctionDetails()
  24.    {
  25.       return getAuctionAction().getAuction();
  26.    }
  27.  
  28.     @WebMethod
  29.    public void setAuctionPrice(double price)
  30.    {
  31.       getAuctionAction().getAuction().setPrice(price);
  32.    }
  33.  
  34.    @WebMethod
  35.    public void confirmAuction()
  36.    {
  37.       getAuctionAction().confirm();
  38.    }
  39.  
  40.    private AuctionActionInt getAuctionAction()
  41.    {
  42.       // Get seam component named "auctionAction" from context
  43.       return (AuctionActionInt) Component.getInstance("auctionAction", true);
  44.    }
  45.    ... ...
  46. }

Notice that the createAuction(), setAuctionDuration(), setAuctionPrice() and confirmAuction() methods all need to happen in the same conversation so that they can access the same "auctionAction" component. But we do not explicitly pass the conversation id to the web service calls. Instead, when the createAuction() method returns, it inserts a conversation id in the SOAP header, and expect the client to use the same conversation id in the header until the caller reaches confirmAuction(), which ends the conversation. The SOAP request inside a conversation looks like the following:

XML:
  1. <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
  2.                            xmlns:seam="http://seambay.example.seam.jboss.org/">
  3.    <soapenv:Header>
  4.       <seam:conversationId>2</seam:conversationId>
  5.    </soapenv:Header>
  6.    <soapenv:Body>
  7.       <seam:setAuctionPrice>
  8.          <arg0>20</arg0>
  9.       </seam:setAuctionPrice>
  10.    </soapenv:Body>
  11. </soapenv:Envelope>

As a proof of concept to demonstrate that Seam web service is well supported by existing SOAP tools, I build a SoapUI script to demonstrate how to add an auction to the Seam app via web services. Notice the "transfer" elements in the script. They are used to maintain the conversation id header across SOAP requests in a conversation.

Picture 17.png

Finally, I'd like to make the SOA version of the seambay example available for download. You can find the ready built EAR file in the dist directory, as well as the SoapUI script in the root directory.

JBoss Seam: A “Deep Integration” Framework

Monday, July 30th, 2007

TheServerSide is running my article this week:

JBossSeamFramework.gif

I like the artwork visualizing "Seam" in an origami bird. Elegant, balanced, and lightweight. Perfect for Seam. The article is based on presentations I recently did on Seam. It targets experienced Java EE developers (i.e., the JUG, NFJS crowd), and goes into depth on some of ideas behind Seam (instead of just a CRUD demo). I hope you enjoy it and let me know your comments. Thanks. Here are some slides from my presentations that are relevant to the article.

Picture 8.png

Picture 9.png

Picture 10.png

Picture 11.png

Picture 12.png

Seam 2.0 and Tomcat

Tuesday, July 24th, 2007

Darryl Smith pointed out that we can actually use non-JTA transactions with JPA in Tomcat now. So, I just added tomcat 5.5 and 6.0 build targets for the jpa example in CVS based on his suggestions.

In JBoss Seam 2.0, we made some changes to the way Tomcat is supported as a Seam runtime. It has caused some confusion. So, let me try to clarify here ...

As you recall, in Seam 1.0 to 1.2, we can run Seam applications on Tomcat by bundling the JBoss Embeddable EJB3 library or the JBoss micro-container inside the WAR application. The application will need to bootstrap the EJB3 container or micro-container upon startup. However, the EJB3 library Jars is more than 20 MB. The idea of bootstraping the entire thing for each application is not very efficient. In Seam 2, we leverage the "Embeddable JBoss" library to provide shared EJB3 service to all WAR applications deployed in the Tomcat instance. You have two ways to run Seam 2 applications in Tomcat:

1. If you need to use EJB3 beans, you will need to install the "Embeddable JBoss" libraries as shared library in Tomcat. It is an easy process. You can find instructions for Tomcat 5.5 and 6.0 respectively. Once you do that, you can deploy Seam applications without any restrictions. You will be able to use full EJB3 features including session beans, entity beans, message driven beans, and web services etc.

Of course, you still cannot deploy EAR files on Tomcat. But you can bundle EJB3 JARs in the WEB-INF/lib directory of your WAR application -- essentially re-creating the EAR structure in a WAR. Just run the tomcat.war ANT target on any of the official Seam examples to see how this is done.

2. If you absolutely cannot install any shared library or shared configuration on Tomcat, you can still run Seam applications. However, you will not be able to use EJB3 features -- you must use Seam POJOs instead. You can, however, use JPA in local transaction mode. Seam manages the transaction manager and entity manager for you in this case.

Checkout the jpa and hibernate2 examples in Seam distribution and build for the tomcat55 or tomcat6 targets to see how this works. The jpa shows how to use JPA EntityManager with Seam POJOs and the hibernate2 example shows how to use Hibernate sessions with Seam POJOs. You will need to copy hsqldb.jar into Tomcat's shared lib directory since the example app assumed that we will use a HSQL DB from JNDI (see META-INF/context.xml). Obviously, you do not have to do that in your own apps.

Okay, so much for Tomcat support. What about Seam 2 support for J2EE 1.4 application servers and non-JBoss Java EE 5 application servers? Here are the status:

  • J2EE 1.4 application servers: Try the jpa example in Seam distribution. It uses Seam POJOs to replace EJB3 session beans in other examples. The jpa example builds for JBoss 4.0.5/4.2.x, WebSphere 6.1.0.9, and WebLogic 9.2.
  • Java EE 5 application servers: Try the jee5 example in Seam distribution. It builds for JBoss AS 5.x, Glassfish V1/V2, and Oracle OC4J 11. We are currently working on WebLogic 10, which has some weird reflection issues.

Hope that helps!