Home » Blog

Tomcat 6 vs Tomcat 7 Threads

Posted by Roger Keays, 8 April 2012, 11:04 AM

The blue line is max threads, the green area is used threads. The same code is run on Tomcat 6 and Tomcat 7.

No comments yet, be the first to comment!

ServletRequest.setCharacterCoding() Ignored

Posted by Roger Keays, 2 April 2012, 3:57 PM

Take a look at this block of servlet code and see if you can tell me what the output should be when I send x=éééé

Log.warning(Charset.defaultCharset().toString());
Log.warning(request.getCharacterEncoding());
Log.warning(request.getParameter("x"));
request.setCharacterEncoding("UTF-8");
Log.warning(request.getCharacterEncoding());
Log.warning(request.getParameter("x"));

Well, here is the output

UTF-8
null
éééé
UTF-8
éééé

Compare this code

Log.warning(Charset.defaultCharset());
Log.warning(request.getCharacterEncoding());
request.setCharacterEncoding("UTF-8");
Log.warning(request.getCharacterEncoding());
Log.warning(request.getParameter("x"));

Which gives us something more sensible:

UTF-8
null
UTF-8
éééé

Lesson of the day?

You can't change the request encoding after request.getParameter() has been called.

In my case a third-party filter was causing the damage, so I made a new filter at the top of the chain just to call request.setCharacterEncoding(). Note also that the default character encoding which I set with -Dfile.encoding=UTF-8 had no effect on the decoding of request parameters. Also, the form is POSTed with multipart/form-data and I added accept-charset to force the browser to send UTF-8:

<form method="post" enctype="multipart/form-data" accept-charset="UTF-8" >
  <input type="text" name="x"/>
  <input type="submit"/>
</form>

Read more...

No comments yet, be the first to comment!

Upgrading To The Java EE 6 Web Profile

Posted by Roger Keays, 21 March 2012, 1:21 PM

Here are my notes from our upgrade of the Sunburnt SEO software to the Java EE 6 Web Profile. Previously our stack was pretty similar to Java Web Profile, just with a lot more dependencies than is now necessary with EE 6.

We can now deploy to Glassfish 3.1 or a modified Tomcat 7.0, since we aren't using the EJB features of Java EE 6.

Code Changes

persistence.xml is now version 2.0

<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" 
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
             http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

web.xml is now version 3.0

<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="3.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
         http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

Remove vendor-specific JPA annotations.

  • //@Index
  • //@ForeignKey
  • //@ElementForeignKey
  • //@ContainerTable
  • //@PersistentMap
  • //import org.apache.openjpa

Read more...

No comments yet, be the first to comment!

java.lang.ClassFormatError Exception With EclipseLink Static Weaving [SOLVED]

Posted by Roger Keays, 19 March 2012, 4:48 AM

Here's an interesting exception that slapped me when I tried out using the EclipseLink static weaver on against a fresh Maven pom.xml for Java EE Web projects. The same exception occurs with the OpenJPA enhancer.

Executing tasks
     [java] Exception in thread "main" java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/persistence/ValidationMode
     [java] 	at java.lang.ClassLoader.defineClass1(Native Method)
     [java] 	at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
     [java] 	at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
     [java] 	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
     [java] 	at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
     [java] 	at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
     [java] 	at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
     [java] 	at java.security.AccessController.doPrivileged(Native Method)
     [java] 	at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
     [java] 	at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
     [java] 	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
     [java] 	at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
     [java] 	at org.apache.openjpa.persistence.PersistenceProductDerivation.configureBeanValidation(PersistenceProductDerivation.java:241)
     [java] 	at org.apache.openjpa.persistence.PersistenceProductDerivation.beforeConfigurationLoad(PersistenceProductDerivation.java:214)

It turns out this obscure error is because the default Java EE jars do not contain any actual code. To fix it, change your Java EE dependencies from

    <!-- Java EE libraries -->
    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-web-api</artifactId>
      <version>6.0</version>
      <scope>provided</scope>
    </dependency>

to

    <!-- default Jave EE jars don't include code necessary fo
         bytecode enhancement so we use these instead -->
    <dependency>
      <groupId>org.jboss.spec</groupId>
      <artifactId>jboss-javaee-6.0</artifactId>
      <version>1.0.0.Final</version>
      <type>pom</type>
      <scope>provided</scope>
    </dependency>

You will also need to add the JBoss repository to your pom.xml if you aren't already using it:

  <repositories>
    <repository>
      <id>repository.jboss.org-public</id>
      <name>JBoss repository</name>
      <url>https://repository.jboss.org/nexus/content/groups/public</url>
    </repository>
  </repositories>

No comments yet, be the first to comment!

java.lang.ClassNotFoundException: com.sun.el.lang.VariableMapperImpl [Fixed] for Glassfish JSF

Posted by Roger Keays, 18 March 2012, 5:34 PM

Using Glassfish 3.1.2, JSF 2.1.x and Facelets with client side state saving, if you pass a bean reference by EL and try to dereference that expression you will get the following error:

Servlet.service() for servlet Faces Servlet threw exception
java.lang.ClassNotFoundException: com.sun.el.lang.VariableMapperImpl
	at org.glassfish.web.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1509)
	at org.glassfish.web.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1359)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:247)
	at com.sun.faces.renderkit.ApplicationObjectInputStream.resolveClass(ApplicationObjectInputStream.java:95)
	at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1574)
	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
	at com.sun.el.MethodExpressionImpl.readExternal(MethodExpressionImpl.java:320)
	at java.io.ObjectInputStream.readExternalData(ObjectInputStream.java:1791)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1750)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
	at com.sun.faces.facelets.el.TagMethodExpression.readExternal(TagMethodExpression.java:158)
	at java.io.ObjectInputStream.readExternalData(ObjectInputStream.java:1791)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1750)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
	at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1666)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1322)
	at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1666)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1322)
	at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1666)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1322)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
	at java.util.HashMap.readObject(HashMap.java:1030)
	at sun.reflect.GeneratedMethodAccessor264.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
	at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1848)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
	at com.sun.faces.renderkit.ClientSideStateHelper.doGetState(ClientSideStateHelper.java:255)
	at com.sun.faces.renderkit.ClientSideStateHelper.getState(ClientSideStateHelper.java:198)
	at com.sun.faces.renderkit.ResponseStateManagerImpl.getState(ResponseStateManagerImpl.java:100)
	at com.sun.faces.application.view.StateManagementStrategyImpl.restoreView(StateManagementStrategyImpl.java:227)
	at com.sun.faces.application.StateManagerImpl.restoreView(StateManagerImpl.java:188)
	at com.sun.faces.application.view.ViewHandlingStrategy.restoreView(ViewHandlingStrategy.java:123)
	at com.sun.faces.application.view.FaceletViewHandlingStrategy.restoreView(FaceletViewHandlingStrategy.java:453)
	at com.sun.faces.application.view.MultiViewHandler.restoreView(MultiViewHandler.java:148)
	at javax.faces.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:303)
	at javax.faces.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:303)
	at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:192)
	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
	at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:116)
	at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)

The workaround is to add el-ri.jar to your project. You can do it in maven like this:

    <dependency>
      <groupId>com.sun.el</groupId>
      <artifactId>el-ri</artifactId>
      <version>1.0</version>
      <scope>compile</scope>
    </dependency>

The problem is tracked by the JAVASERVERFACES-1828 bug.

No comments yet, be the first to comment!

Change J2EE Version Of Netbeans Maven Project

Posted by Roger Keays, 16 March 2012, 6:07 PM

For Maven projects, Netbeans determines the J2EE version shown in the project properties by looking at the version of web.xml:

  • web.xml 2.4 -> J2EE 1.4
  • web.xml 2.5 -> J2EE 1.5
  • web.xml 3.0 -> J2EE 1.6

You have to restart Netbeans to see the changes.

No comments yet, be the first to comment!

WTF Triple Negative!

Posted by Roger Keays, 16 March 2012, 4:44 PM

Check out this JPA parameter:

<exclude-unlisted-classes>false</exclude-unlisted-classes>

Now see if you can tell me if it includes my listed classes.

No comments yet, be the first to comment!

How To Show Negative Numbers Using Brackets With NumberFormatter In Java

Posted by Roger Keays, 15 March 2012, 8:46 AM

If you want to use parentheses around your negative numbers, you can do it in Java like this:

NumberFormat formatter = NumberFormat.getCurrencyInstance(locale);
if (formatter instanceof DecimalFormat) {
    DecimalFormat f = (DecimalFormat) formatter;
    f.setNegativePrefix("(" + f.getPositivePrefix());
    f.setNegativeSuffix(")");
}
String output = formatter.format(value);

This snippet will retain the localised currency formatting set by NumberFormat.

No comments yet, be the first to comment!

How To Check If The Software Keyboard Is Shown In Android

Posted by Roger Keays, 21 February 2012, 10:11 AM

Here is a method to detect if the soft keyboard is visible on the screen in Android. All the other methods I have seen test the height of screen elements to guess whether it is displayed. This doesn't work for keyboards like WifiKeyboard which is an invisible keyboard.

This method uses the callback result of InputMethodManager.showSoftInput() to determine if the keyboard status changed. This is suitable for me because I need to call showSoftInput() anyway if the keyboard is not shown. The result from the operation needs to be polled because it is asynchronous. This example only polls 500 milliseconds and assumes that anything longer than that is caused by the keyboard being loaded and rendered.

Here is how the code is used:

// try to show the keyboard and capture the result
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
IMMResult result = new IMMResult();
imm.showSoftInput(editText, 0, result);

// if keyboard doesn't change, handle the keypress
int res = result.getResult();
if (res == InputMethodManager.RESULT_UNCHANGED_SHOWN ||
        res == InputMethodManager.RESULT_UNCHANGED_HIDDEN) {
    showTags();
}

Read more...

3 comments, post a comment!

How To Move A Node In Nested Sets With SQL

Posted by Roger Keays, 8 January 2012, 3:35 PM

Moving nodes in nested sets is a complex operation. There were a few solutions on Stack Overflow for moving a node under a given parent, however this doesn't let you select the position of the node amongst it's siblings.

This solution lets you move a node to any position in the tree, with just a single input parameter - the new left position (newpos) of the node.

Fundamentally there are three steps:

  1. Create new space for the subtree.
  2. Move the subtree into this space.
  3. Remove the old space vacated by the subtree.

In psuedo-sql, it looks like this:

    /**
     *  -- create new space for subtree
     *  UPDATE tags SET lpos = lpos + :width WHERE lpos >= :newpos
     *  UPDATE tags SET rpos = rpos + :width WHERE rpos >= :newpos
     * 
     *  -- move subtree into new space
     *  UPDATE tags SET lpos = lpos + :distance, rpos = rpos + :distance
     *           WHERE lpos >= :tmppos AND rpos < :tmppos + :width
     * 
     *  -- remove old space vacated by subtree
     *  UPDATE tags SET lpos = lpos - :width WHERE lpos > :oldrpos
     *  UPDATE tags SET rpos = rpos - :width WHERE rpos > :oldrpos
     */

Read more...

No comments yet, be the first to comment!

Android ORM / JPA

Posted by Roger Keays, 19 December 2011, 6:01 AM

Coming from the server-side, I find it hard to live without ORM (Object-Relational Mapping) such as JPA. Now that I've started writing Android Apps, I set about finding a JPA ORM tool for Android.

Here is a comparison of the tools I found that do ORM and are lightweight enough for use with Android.

Annotations DB Ops Size License Docs Age
OrmLite JPA or custom DAO or Entity 200kb Open docs 1yr
ORMAN JPA-like Entity 170kb Apache2 wiki 2yrs
greenDAO N/A Codegen DAO or Entity <100kb Apache2 docs
ActiveAndroid JPA-like Entity $20 wiki
AndrORM None docs 1yr

"DB Ops" refers to how database operations such as persist() and update() are handled. Normally either by a DAO (data access object) or by the entity themselves.

Handling Large Data Sets

Performance counts - especially since I need to handle large data sets. I don't want to load 3000 records into memory at once when the device only has room to display 10 at a time. Native Android supplies a Cursor to interate large data sets, and some ORM tools provide their own method too.

greenDAO has Query.lazyList() and OrmLite has DAO.iterator(Query) to do this, however Android adapters do not bind to an iterator so a custom adapter would need to be written in any case. There is a thread online that discusses this, however I think I can rig up a something similar to my LazyList for JPA to make this happen.

Verdict

I've started my project with OrmLite because it is the most mature. Lazy loading query results will need some custom code, but in the long run I think it will be better than polluting my code with column names and SQL hacks.

greenDAO was a good candidate from the performance perspective, but really I want to write my Entities myself so I can add the methods that I need.

5 comments, post a comment!

Alt-Tab Shortcuts Broken In Ubuntu Lucid With XModMap

Posted by Roger Keays, 15 December 2011, 6:52 AM

I use xmodmap to turn caps-lock into an extra modifier for special keys and shortcuts. Since upgrading finally to Ubuntu Lucid 10.04 LTS, I've had a problem with the Caps-Lock modifier key (Mode_switch) getting stuck when I accidentally press the Shift key. When I get it unstuck by pressing the same combination of Caps, Shift and one of my special keys, all my X-Windows shortcuts like Alt-Tab and Function keys stop working.

It's freaking annoying, however I finally found a workaround in Red Hat Bug 513815 and Bug 508434...

$ setxkbmap -layout jp

This resets your keyboard to it's original state. In my case the layout is japanese. You will probably want 'us' for US keyboards. Now you can reapply your xmodmap settings:

$ xmodmap ~/.xmodmaprc

It's still flaky, but it gets me back on the road.

No comments yet, be the first to comment!

1 2 3 4 5 6 7 8