WKBReader: ParseException: Unknown WKB type x

I’m using the Java API JTS Topology Suite to do spatial operations. To convert a byte array into a Geometry object the following helper class was used:

public class JTSHelper {
	static WKBReader wkbReader = new WKBReader();

	public static Geometry bytesToGeometry(byte geometryBytes[]) throws ParseException {
		return wkbReader.read(geometryBytes);
	}
}

This seemed to work well, but in the logfile we saw intermittent failures caused by this class:
ParseException: Unknown WKB type 139
ParseException: Unknown WKB type 0
ParseException: Unknown WKB type 17

The WKB type numbers were always different, but when checking the incoming byte arrays everything seems to be OK.

With apache benchmark tool the failures could be reproduced when increasing the number of concurrent requests:
ab -n 1000 -c 10 http://localhost:8080/project/test-action

A look at JavaDoc of WKBReader shows that this class is not thread-safe. Therefore the solution is to put WKBReader in ThreadLocal:

public class JTSHelper {
	static ThreadLocal<WKBReader> wkbReader	= new ThreadLocal<WKBReader>() {
		protected WKBReader initialValue() { return new WKBReader(); };
	};

	public static Geometry bytesToGeometry(byte geometryBytes[]) throws ParseException {
		WKBReader reader = wkbReader.get();
		return reader.read(geometryBytes);
	}
}

Versions: JTS 1.8, JDK 5

Posted in Java. Tags: , , . Leave a Comment »

Tomcat: Getting the process ID

If you want to get the process id (PID) of your tomcat you can do something like this:

ps h -C java -o "%p:%a" | grep catalina | cut -d: -f1

If you want to kill this tomcat, because it didn’t shut down properly you can use the following:

kill -9 `ps h -C java -o "%p:%a" | grep catalina | cut -d: -f1`

A better way is to set the environment variable CATALINA_PID. If this variable is set the PID is written in the specified file (here catalina.pid) on tomcat startup.

export CATALINA_PID=/opt/tomcat/catalina.pid
/opt/tomcat/bin/startup.sh

Now killing the tomcat is also easier: You can can stop tomcat with -force, which will kill the tomcat process after shutdown (-force only works if CATALINA_PID is set).

export CATALINA_PID=/opt/tomcat/catalina.pid
/opt/tomcat/bin/shutdown.sh -force

(If you set CATALINA_PID in your .bashrc you don’t have to set it before startup/shutdown)

Eclipse open GSP-page: Editor could not be initialized

I’m using Eclipse with the SpringSource Tool Suite. After importing a Grails Project, I wanted to open a GSP-page but got the following error in the Editor: Could not open the editor: Editor could not be initialized.

The stacktrace looks as follows:

java.lang.NullPointerException
    at com.springsource.sts.grails.editor.gsp.tags.GSPModelQueryCMProvider.(GSPModelQueryCMProvider.java:53)
    at com.springsource.sts.grails.editor.gsp.tags.GSPModelQueryImpl.(GSPModelQueryImpl.java:36)
    ...
    at org.eclipse.equinox.launcher.Main.main(Main.java:1287)

The error occurs because Eclipse (STS) wants to open GSP-files with the GSP Editor (because of File Associations) even if the project is not a Grails Project.

So the solution is to convert the project in a Grails Project: right click on your project → “Configure” | “Convert to Grails-Project”.

Resources:

Versions: Eclipse 3.5, STS 2.3, Grails 1.1.1

Posted in Grails. Tags: , , . Leave a Comment »

Grails and UrlRewriteFilter: Problem with Params

I’m using UrlRewriteFilter to map some legacy URLs to our new Grails application. It’s configured as follows:

web.xml

...
<filter>
    <filter-name>rewriteFilter</filter-name>
    <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>charEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>sitemesh</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
	<filter-name>rewriteFilter</filter-name>
	<url-pattern>/*</url-pattern>
	<dispatcher>REQUEST</dispatcher>
	<dispatcher>FORWARD</dispatcher>
</filter-mapping>

urlrwrite.xml

...
<rule>
	<from>^/legacy-search-url$</from>
	<to last="true">/search/result</to>
	<set type="parameter" name="pagesize">5</set>
</rule>

Now I had the problem that the forward worked as expected (SearchController with action “result” was invoked), but in params parameter pagesize was missing.

After a while of debugging I found out the following:
GrailsWebRequest, which holds the params is created with the GrailsWebRequestFilter. This filter is added to the web.xml in the controllers-plugin and the filter-mapping is placed at the end or after the charEncodingFilter. In my case after charEncodingFilter and so before the rewriteFilter:

generated web.xml

<filter-mapping>
    <filter-name>charEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
	<filter-name>grailsWebRequest</filter-name>
	<url-pattern>/*</url-pattern>
	<dispatcher>FORWARD</dispatcher>
	<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
	<filter-name>sitemesh</filter-name>
	<url-pattern>/*</url-pattern>
	<dispatcher>REQUEST</dispatcher>
	<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter-mapping>
	<filter-name>rewriteFilter</filter-name>
	<url-pattern>/*</url-pattern>
	<dispatcher>REQUEST</dispatcher>
	<dispatcher>FORWARD</dispatcher>
</filter-mapping>

That means that the params-object is created before the rewriting happens, which explains that the pagesize parameter is not there. The solution is to place the rewriteFilter in first position of the filter-mapping or at least before the charEncodingFilter (if present).

Rethinking the problem I had the opinion that it should work regardless to the order, as the grailsWebRequest-filter has a forward dispatcher and should be called again after the rewriting. That’s correct so far, but as GrailsWebRequestFilter extends OncePerRequestFilter the GrailsWebRequest is not recreated on the second call.

Hint: If you are using the URL Rewrite Plugin, you will have the same problems, as it is loaded after the controllers-Plugin.

Versions: Grails 1.1.1

Posted in Grails. Tags: . 1 Comment »

Error in Grails documentation of URL Mappings exclude

In 6.4.6 Mapping Wildcards is written that you exclude URIs like this:

static excludes = ["/images/**", "/css/**"]

But this didn’t work for me. Looking at the source code (UrlMappingsFilter) I found out, that the exclude is no wildcard pattern matching and only a startsWith matching:
for (String excludePattern:excludePatterns){
    if (uri.equals(excludePattern)||
            (excludePattern.endsWith("*")&&
                    excludePattern.substring(0,excludePattern.length()-1).
                            regionMatches(0,uri,0,excludePattern.length()-1))){
        processFilterChain(request, response, filterChain);
        return;
    }
}

So the correct way is with one asterisk:
static excludes = ["/images/*", "/css/*"]

Testing your Hibernate Annotation Mapping

To test if I my mappings are correct, I use the following Java Application which uses SchemaExport. It gives me the SQL-statements and executes them against a database.
To protect the production database, you can either set the second parameter of create() to false and/or change the connection string to a test database.
configuration.setProperty(Environment.URL, "jdbc:mysql://localhost/test");

package starter;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Environment;
import org.hibernate.tool.hbm2ddl.SchemaExport;

public class SchemaTester {
    
    public static void main(String[] args) throws ClassNotFoundException {
        AnnotationConfiguration configuration = new AnnotationConfiguration();
        
        List<Class> classes = findClasses(new File("src/domain"), "domain");
        for (Class clazz : classes) {
            configuration.addAnnotatedClass(clazz);
        }
        
        configuration.configure();
        configuration.setProperty(Environment.URL, "jdbc:mysql://localhost/test");
        
        SchemaExport schemaExport = new SchemaExport(configuration);
        schemaExport.create(true, true);        
        // schemaExport.execute(true, false, false, true); // to see just create statements
    }
    
    private static List<Class> findClasses(File directory, String packageName) 
                                                                throws ClassNotFoundException  {
        List<Class> classes = new ArrayList<Class>();
        if (!directory.exists()) {
            return classes;
        }
        File[] files = directory.listFiles();
        for (File file : files) {
            System.out.println(file);
            if (file.isDirectory()) {
                if(!file.getName().contains(".")) {
                    classes.addAll(findClasses(file, packageName + "." + file.getName()));                    
                }
            } else if (file.getName().endsWith(".java")) {
                String javaName = file.getName().substring(0, file.getName().length() - ".java".length());
                classes.add(Class.forName(packageName + '.' + javaName));
            }
        }
        return classes;
    }
}

Resources

Why does MySQL not write the log file?

I wanted to switch on the query log of MySQL. So I added the following to /etc/my.cnf

[mysqld]
log = /var/log/mysql.log

and restarted the server: sudo /etc/init.d/mysql restart, but no log file occured even if I executed some queries.

The Problem was that mysql had no rights for /var/log. So the solution was to create an own directory for mysql

cd /var/log
sudo mkdir mysql
sudo chown mysql:mysql mysql/

and log into it:
log = /var/log/mysql/mysql.log

jQuery iframe-ThickBox removes parameter

I had a iframe-ThickBox link with a strange behaviour: Clicking on it leads to an application error (because the id param was missing), copying the url in a new browser tab worked well.

<a href="/controller/action?TB_iframe=true&height=500&width=650&id=123">link</a>

What happened? jQuery-Thickbox removes all parameters after TB as mentioned in the description:
Important to Remember:
Add all other query parameters before the TB_iframe parameters. Everything after the “TB” is removed from the URL.

So rearranging the order fixed the problem.

<a href="/controller/action?id=123&TB_iframe=true&height=500&width=650">link</a>

The real problem was not so obvious, because we use a link-Tag which transformed the URL in a map to add parameters and transformed it back to a URL. In that transformation the order got lost. We fixed that problem with a LinkedHashMap instead of HashMap.

@Transactional not always works on methods

Although I had annoted my method as @Transactional no transaction was started. Situation was the following:

applicationContext.xml

...
<!-- Enable @Transactional support -->
<tx:annotation-driven transaction-manager="transactionManager" />
...

Test.java

class Test {
    public static void main(String args[]) throws Exception {
        ...
        Test test = factory.getBean("test");
        test.run();
    }

    public void run() {
        // code before transaction
        runTransactional();
        // code after transaction
    }

    @Transactional
    public void runTransactional() {
        // code in transaction
    }
}

I found the reason in a little hint in the Spring Documenation (Using @Transactional):

Note: In proxy mode (which is the default), only ‘external’ method calls coming in through the proxy will be intercepted. This means that ‘self-invocation’, i.e. a method within the target object calling some other method of the target object, won’t lead to an actual transaction at runtime even if the invoked method is marked with @Transactional!

So the solution is either to use aspectj instead of proxy-mode or to make an ‘external’ method call. I used the second. So I head to move the code from run() to main() so that I have an ‘external’ method call to runTransactional().

Test.java

class Test {
    public static void main(String args[]) throws Exception {
        ...
        Test test = factory.getBean("test");
        // code before transaction
        test.runTransactional();
        // code after transaction
    }

    @Transactional
    public void runTransactional() {
        // code in transaction
    }
}

Follow

Get every new post delivered to your Inbox.