Tuesday, September 20, 2011

Running ant task in maven

Sometimes you have some task that you just need to execute: without attaching to build phase, or any process - just run. Unfortunately maven is not very flexible about it. Fortunately, it is still possible. To do it, you need use antrun plugin with custom profile. For example, like this:

<profiles>
  <profile>
     <id>deploy</id>
     <build>
        <plugins>
          <plugin>
            <artifactId>maven-antrun-plugin</artifactId>
            <version>1.3</version>
            <configuration>
              <tasks>
                <property file="user.properties" prefix="user"/>
                <scp file="target/target.war" todir="${user.login}:${user.password}@${user.server}:/home/user/" trust="true"/>
                <sshexec host="${user.server}" username="${user.login}" password="${user.password}" command="sudo ./redeploy.sh" trust="true" />
              </tasks>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>org.apache.ant</groupId>
                    <artifactId>ant-jsch</artifactId>
                    <version>1.7.1</version>
                </dependency>
                <dependency>
                    <groupId>com.jcraft</groupId>
                    <artifactId>jsch</artifactId>
                    <version>0.1.42</version>
                </dependency>
            </dependencies>
          </plugin>
        </plugins>
     </build>
  </profile>
...

</profiles>

Later, you can run this script like:


mvn antrun:run -Pdeploy

Of course you can have different scripts in several profiles.

This approach even has advantages over having separate Ant's build.xml - you don't need to have separate Ant installation, or for instance, with example above, you don't need to download jsch plugin separately - it is all done by Maven.

Friday, September 16, 2011

Java web application monitoring tool

I was looking for production monitoring tool recently. I didn't have any specific requirements, just to have some understanding about load and bottlenecks. Finally, after some googling I found one very interesting option JavaMelody.

This tool takes risky, but very interesting approach, proxies JDBC calls, loads as web filter, advisor for Spring, etc. Additionally, it watches usual VM stuff, like JMX. As result it has a lot of very detailed and deep statistics, like sql queries time, page load times, and so on. Also it provides a lot of graphics and tables, to watch, generally looks nice and advanced. Of course with this approach it looks quite dangerous, but seems like this is already mature tool and I would like to try to use it in my projects.

Also, it has very nice and simple integration with Grails. Just install Grails-melody plugin, and you have your statistics under URL <hostname:port/app-ctx>/monitoring. This is regular application URL, so you can easily configure access rights and login in your application.

Thursday, September 1, 2011

Hibernate "not-found" in Grails

Often when you delete object from db instead of just marking it as deleted, there is nasty exception that this object is referenced by someone else.
2011-09-01 15:18:38,953 [http-8080-1] ERROR errors.GrailsExceptionResolver  - Exception occurred when processing request: [GET] xxx
Stacktrace follows:
org.codehaus.groovy.grails.web.pages.exceptions.GroovyPagesException: Error processing GroovyPageView: Error executing tag <g:form>: Error executing tag <sec:ifAllGranted>: Error evaluating expression [xxx.yyy?.id] on line [70]: No row with the given identifier exists: [xxx#21244] at xxx.gsp:71 at xxx.gsp:102
    at java.lang.Thread.run(Thread.java:662)
Caused by: org.codehaus.groovy.grails.web.taglib.exceptions.GrailsTagException: Error executing tag <g:form>: Error executing tag <sec:ifAllGranted>: Error evaluating expression [xxx.yyy?.id] on line [70]: No row with the given identifier exists: [yyy#21244] at xxx.gsp:71 at xxx.gsp:102
    ... 1 more
Caused by: org.codehaus.groovy.grails.web.taglib.exceptions.GrailsTagException: Error executing tag <sec:ifAllGranted>: Error evaluating expression [xxx.yyy?.id] on line [70]: No row with the given identifier exists: [xxx#21244] at xxx.gsp:71
    ... 4 more
Caused by: org.codehaus.groovy.grails.web.pages.exceptions.GroovyPagesException: Error evaluating expression [xxx.yyy?.id] on line [70]: No row with the given identifier exists: [xxx#21244]
    at grails.plugins.springsecurity.SecurityTagLib$_closure1.doCall(SecurityTagLib.groovy:60)
    ... 7 more
Caused by: org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [xxx#21244]
    ... 10 more
In Hibernate there is nice not-found="ignore" for such cases. In Grails/GORM there is similar option which is not documented for some reason. Just add ignoreNotFound to domain objects mapping section and that is it. For example:
class Log {
  User user

  static mapping = {
    user ignoreNotFound : true 
  }

}