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)

Posted in Tomcat. Tags: . 1 Comment »

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.