Archive

Archive for April, 2009

Two different mocking approaches

April 22nd, 2009 2 comments

Whether you choose to choose to adopt TDD or a more traditional approach, you will test your classes in isolation. This usually mean you code with interfaces and inject your dependencies in your classes.

Last year, I had to test a servlet. Servlets are the showcase to demonstrate out-of-container testing because of their dependencies to said container in their doXxx() method. Every one of these methods has a dependency on HttpServletRequest and HttpServletResponse. Both are interfaces that have no concrete implementations in the Servlet API. So, basically, in your tests, you’re stuck with three options:

  1. Use your container implementations (yuck!),
  2. Create your own implementations (rather time-consuming),
  3. Use already available implementations that have no dependencies.

Choosing option the 3rd option, I found this little jewel, MockRunner. MockRunner put at your dispositions mock implementations for the following API and frameworks: Read more…

Categories: Java Tags: , , , ,

Google AppEngine limitations for Java (and how to overcome them)

April 10th, 2009 8 comments

Since the start of Google’s App Engine for Java, I have tried to create a small but representative project and to deploy it on Google’s infrastructure. I have learned much, mainly by making mistakes. Interestingly enough, there are much that I achieved I didn’t hope I would. On the contrary, the Devil is in the details, as they say, and I found some problems I couldn’t imagine there: for some, there are other solutions, for some, there aren’t.

Eclipse

Eclipse is my first and foremost IDE. I tried NetBeans but, though I am NetBeans certified, it was too strange for me to work with. Anyway, Google provides an Eclipse plugin for GAE. When I tried to install it with the update site, I had a not so nice error popup:

Cannot complete the install because one or more required items could not be found.
Software being installed: com.google.gdt.eclipse.suite.e34.feature.feature.group 1.0.0.v200904062334
Missing requirement: com.google.gdt.eclipse.suite.e34.feature.feature.group 1.0.0.v200904062334 requires \
    'org.eclipse.platform.feature.group [3.4.0,3.5.0)' but it could not be found

Google’s plugin only works with version 3.4 (Ganymede) and I have version 3.5 (Galileo). So long for Eclipse, yet it seems Google plans to release a Galileo compatible version no later than Galileo own’s release (thanks Rajeev).

Maven

Like every not-so-young Java developer, I was proficient in Ant once. But I was bored to script the same tasks for every project, so I let Maven seduce me. It seems people at Google are still using only Ant (there’s no reference to Maven in GAE documentation), so you have to do the following if you want to use Maven:

  • Reference DataNucleus repository. Here’s the url : http://www.datanucleus.org/downloads/maven2,
  • Add dependencies to :
    • org.datanucleus:datanucleus-core:1.1.0:jar,
    • org.datanucleus:datanucleus-jpa:1.1.0:jar,
    • org.datanucleus:datanucleus-enhancer:1.1.0:jar,
  • datanucleus-core has a dependency on javax.jta:transaction-api:1.1:jar. Since its POM references a local repository (!), this artifact won’t be found. You have to install manually JTA 1.1 under this name,
  • Install manually and add dependencies to :
    • org.datanucleus:datanucleus-appengine:1.0.0.final:jar,
    • com.google.appengine:appengine-api:1.0:jar.

Spring

Spring works like a charm in GAE. GAE’s documentation says that reflection is near fully supported, so this shouldn’t come as a surprise. I didn’t use AOP though.

Commons-logging

Commons-logging is a dependency of many frameworks, Spring included. On the local server, everything runs fine. In the cloud, Google App Engine infrastructure replaces the commons-logging-1.1.1.jar with a JAR of its own that has a different package structure. In effect, that means you get funny NoClassDefFoundError on org.apache.commons.logging.LogFactory even though you included the JAR as a dependency. The solution is to still include the classes, but to give the JAR another name.

Since I use Maven, I removed the commons-logging dependency from the WAR with the exclusion tag for Spring and MyFaces artifact. Then, I added a dependency on commons-logging:commons-logging-api:1.1:jar with the runtime scope. This jar won’t be replaced.

JSP

JSP work fine in pages. Yet, XML format JSP doesn’t seem to get translated. You need to create “classic” JSP.

Still, you may run into some funny exception. It will look like this:

java.lang.ClassCastException: SomeException cannot be cast to javax.servlet.ServletException
    at org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:754)
    at org.apache.jsp.some_jsp._jspService(some_jsp.java:some_line)

It seems ther’s a bug in the PageContextImpl class where any RuntimeException will be cast to ServletException and thus end up creating another exception. It is very hindering since the ClassCastException‘s stack trace will hide the first one’s stack trace. In order to debug, I advise you to use the following code snippet in the incriminated JSP:

<% try { %>

... your JSP body...

<% } catch (RuntimeException e) {

    Logger log = Logger.getLogger(getClass().getName());
    StringWriter sw = new StringWriter();
    e.printStackTrace(new PrintWriter(sw));
    log.severe(sw.toString());
    throw e;

} %>

EL

EL syntax in JSF tags (#) run fine. For EL syntax in JSTL taglibs – core for example ($), it didn’t work at first. Thanks to Jim, I know now you have to tell the App Engine not to ignore it with the code <%@ page isELIgnored="false" %> on each page you use EL with JSTL. IMHO, it could be a default behaviour, like in Tomcat, for example.

JSF

Apache MyFaces v1.1 works nicely. I had a problem with version 1.2: apparently, there was an API mismatch somewhere. So I’m stuck with the older version for now.

JPA

GAE’s persistence API of choice is JDO. Come on, guys, JDO in 2009? Still, GAE accepts JPA as an alternate persistence API, so you can use it, with caution. In both cases, GAE uses the DataNucleus framework (first time I heard of it – it seems related to JDO JPOX team). This framework, like any JDO framework enhances your entity classes with custom byte-code: this takes place in the build process after compilation. What’s very surprising with DataNucleus is that even if you choose JPA as your persistence API, you have to enhance your entity classes.

Since the enhancement process is dependent on some artifacts, check whether these artifacts are referenced as dependencies (see above for list). To bind the enhancement to the compile phase, use the following snippet in your POM (thanks Andy):

<build>
...
    <plugin>
        <groupId>org.datanucleus</groupId>
        <artifactId>maven-datanucleus-plugin</artifactId>
        <version>1.1.0</version>
        <configuration>
            <mappingIncludes>net/frankel/hr/cra/model/*.class</mappingIncludes>
            <verbose>true</verbose>
            <api>JPA</api>
        </configuration>
        <executions>
            <execution>
                <phase>compile</phase>
                <goals>
                    <goal>enhance</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
...
</build>

Using Datanucleus presents another limitation in that if you query using JPA (or JDO), you have to explicitly call the size() method on the resulting List. Otherwise, your JSP will throw a not-so-nice NucleusUserException labeled “Object Manager has been closed”. There’s an issue raised on the datanucleus-appengine integration project.

Local AppEngine server

Local server runs fine. I can’t help wondering why the translation / compilation process takes som much time (measured in minutes) though. Once it’s done, page rendering is very swift, since I think the server optimizes caching.

Deploying the application

The initial appcfg.cmd launches a Java class. I don’t know why but the application just ignores the JAVA_HOME environment variable and keeps checking for the java.home system property. If the latter is not found, it tries to use C:\Program Files\Java\jre6\bin and C:\Program Files\Java\bin looking for javac. Then it fails if not found… I had to modify the appcfg.cmd to put this command line (modification in bold and italic):

@java -Djava.home="%JAVA_HOME%" -cp "%~dp0\..\lib\appengine-tools-api.jar" com.google.appengine.tools.admin.AppCfg %*

Anyway, it avails to nothing because I get this following SSL exception:

Unable to upload:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: No trusted certificate found
	at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)
	at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
	at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
	at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
	at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
	at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
	at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown Source)
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(Unknown Source)
	at com.google.appengine.tools.admin.ServerConnection.connect(ServerConnection.java:295)
	at com.google.appengine.tools.admin.ServerConnection.getAuthToken(ServerConnection.java:215)
	at com.google.appengine.tools.admin.ServerConnection.authenticate(ServerConnection.java:189)
	at com.google.appengine.tools.admin.ServerConnection.send(ServerConnection.java:116)
	at com.google.appengine.tools.admin.ServerConnection.post(ServerConnection.java:66)
	at com.google.appengine.tools.admin.AppVersionUpload.send(AppVersionUpload.java:345)
	at com.google.appengine.tools.admin.AppVersionUpload.beginTransaction(AppVersionUpload.java:159)
	at com.google.appengine.tools.admin.AppVersionUpload.doUpload(AppVersionUpload.java:68)
	at com.google.appengine.tools.admin.AppAdminImpl.update(AppAdminImpl.java:41)
	at com.google.appengine.tools.admin.AppCfg$UpdateAction.execute(AppCfg.java:469)
	at com.google.appengine.tools.admin.AppCfg.(AppCfg.java:114)
	at com.google.appengine.tools.admin.AppCfg.main(AppCfg.java:59)
Caused by: sun.security.validator.ValidatorException: No trusted certificate found
	at sun.security.validator.SimpleValidator.buildTrustedChain(Unknown Source)
	at sun.security.validator.SimpleValidator.engineValidate(Unknown Source)
	at sun.security.validator.Validator.validate(Unknown Source)
	at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(Unknown Source)
	at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
	at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
	... 24 more

The solution is to use the JRE bundled in your JDK. The command line thus becomes:

@java -Djava.home="%JAVA_HOME%/jre" -cp "%~dp0\..\lib\appengine-tools-api.jar" com.google.appengine.tools.admin.AppCfg %*

Now everything should run perfectly from here. Have fun!

To go further:

Categories: JEE Tags: ,

Free Java hosting

April 8th, 2009 No comments

They did it! Yes, they did it! Since a long time, PHP hosting is avalaible freely on the web from a multitude of providers but when you search the web for free Java hosting you find… nothing. Mark today as a the day Java free hosting came to reality: they did it!

Who? Them, the techies from Google now support Java as their second language on Google App Engine. GAE leverages the entire Google infrastructure to host your web applications. Strangely enough, it was until then only available for the Python language. Now it’s not the case anymore. No need to pay for dedicated hosting. Just create your JEE application, add a small proprietary file for the App Engine and deploy using Google’s tools. Google’s infrastructure provides:

  • Java 6 Virtual Machine,
  • Servlets and JSP API (version undocumented),
  • support for standard interfaces to the App Engine datastore and services (JDO, JPA, JavaMail, JCache)

But since there’s no such thing as a free lunch, the only thing to do to have these things for free is to be under the following quotas:

  • 1,300,000 http requests per day,
  • 10,000 calls to Data store service per day,
  • and so on

Since these limits are very high for a personal website or even a small company’s one, it seems to the days of free Java hosting have come. In a next post, I’ll probably be creating a simple Java application to host. Until then, have fun.

To go further:

Categories: JEE Tags: , ,

Custom LoginModule in Tomcat

April 3rd, 2009 7 comments

Tomcat manages application security through the concept of realm. A realm is a coherent package of name password pairs that identify valid users for a web application.

Tomcat’s default realm is MemoryRealm. This realm reads the famous conf/tomcat-users.xml file and uses it check for name password pair validity. Tomcat also provides realms to check against pairs stored in a database, either through a direct connection, or through a configured datasource. The main disadvantage of these all these realms is that they force you to adopt Tomcat’ expected data structure. In most organizations, these constraints will be enough for the architect to rely upon custom or 3rd-party security components.

In order to use your enterprise database structure, you would code a custom realm. Tomcat provides the org.apache.catalina.Realm interface. The drawback of implementing your own realm is that if you change your application server afterwards, all of your code would have been for naught. Yet, if you check Tomcat documentation thoroughly, you will see Tomcat also provides a JAASRealm. JAAS is the Java security feature and enable you to write custom security modules in a portable way. Tomcat’s JAASRealm performs as a adapter between realms and login modules so you only have to write a LoginModule and Tomcat will know how and when to call it. Read more…

Categories: JEE Tags: , , , ,