Implementing a Java-based AWS Lambda Function triggered by SNS

I had some initial trouble finding documentation on how to consume AWS SNS events from a Lambda function implemented in Java. The signature can’t be your domain POJO it seems, it has to be a SNSEvent. Here’s what worked for me:

Maven dependencies:

<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
</dependency>

The signature in the Java-based Lambda Function need to consume com.amazonaws.services.lambda.runtime.events.SNSEvent:

public String processSnsEvent(SNSEvent event, Context context) {
String input = event.getRecords().get(0).getSNS().getMessage();
return processInputFooBarSomething(input)
}

Advertisements
Implementing a Java-based AWS Lambda Function triggered by SNS

Remote Java Debugging via SSH Tunnel Only Works if Local and Remote Ports are Identical

Yepp. At least that’s what I found.

Summary

Remote debugging a Java application from Eclipse (or other IDE)  is a great tool. Even if the source code is not available and decompilation due to legal restrictions a no-no: IDEs will allow you to step through the code, showing a strack trace and variable values. This is an often underrated tool to figure out what the hack is going on, especially in someone else’s code.

If your Java application is not only running in a different JVM, but on a different host (such as a virtual machine or a cloud instance), then SSH may be the only secure way to connect to the host. The only way I got the combination of SSH and remote debugging working however, is if I create a SSH tunnel where local and remote port are identical. This may be due to exotic network settings or the actual nature of technology – don’t care, don’t care, don’t care.

How To

If you’re not sure how to set it up:

Start your remote Java application with the following extra options:

-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=80

Create the SSH tunnel (Ubuntu example):

sudo ssh username@hostname -L 80:127.0.0.1:80

Then create a remote debug configuration in Eclipse, pointing to localhost and port 80. Evidently, the choice of port 80 is arbitrary, any port that is not taken on both, local and remote host will do. Also note that if the default ssh port 22 is closed on either side, then the SSH server can be configured to listen to e.g. 443 or another open port. In this case, add ‘-p 443’ to the ssh command.

Remote Java Debugging via SSH Tunnel Only Works if Local and Remote Ports are Identical

Runtime Enhancement with JDO and Datanucleus

Now there’s a nice discovery I recently made in the world of JEE development: Datanucleus is a persistence API that does not depend on the underlying persistence mechanism. Meaning you won’t have to change your POJOs if you decide to move from RDBMS to Amazon S3, XML, JSON, MS Excel or any other of the various supported mechanisms. The specifics on the persistence are kept in a configuration file,  entities can be annotated via JDO’s @PersistenceCapable. In my view this absolutely rocks. I will prefer it over JPA from now on.

The way it works is that annotated classes are ‘enhanced’, meaning their bytecode is modified to include all the necessary functionality. This can be done at build time: Ant tasks and a Datanucleus Eclipse plugin are part of the package.

There’s a small catch: I happen to develop JEE applications via Eclipse, with hot deployment to an application server and EJB modules split across different projects. After a while I got annoyed by:

  • Noticeable delays caused by enhancement: with Eclipse set to ‘build automatically’, each recompilation causes the enhancer plugin to run. This is the case even if the class compiled is not an entity. It takes long enough to be noticed by the impatient.
  • Hot deployment failures due to synchronisation issues between enhancer and deployer (Glassfish Eclipse in my case).
  • I’d prefer to have a single process for enhancement, instead of having to update my Ant scripts and using the Eclipse plugin as well.
.

The elegant solution provided by Datanucleus is enhancement at runtime, not build time:

    JDOEnhancer enhancer = JDOHelper.getEnhancer();
    enhancer.setClassLoader(this.getClass().getClassLoader());
    enhancer.setVerbose(true);
    enhancer.addPersistenceUnit("my-persistence-unit");
    enhancer.addClasses(BlueEntity.class.getName());
    // add entities to be enhanced to this list...
    enhancer.enhance();
    Properties properties = new Properties();
    properties.setProperty("javax.jdo.PersistenceManagerFactoryClass",
         "org.datanucleus.jdo.JDOPersistenceManagerFactory");
    properties.setProperty("javax.jdo.option.PersistenceUnitName",
         "my-persistence-unit");
    PersistenceManagerFactory factory =
         JDOHelper.getPersistenceManagerFactory(properties, 
            this.getClass().getClassLoader());
    PersistenceManager persistenceManager =
        factory.getPersistenceManager();
.

Important notes: there’s a few catches:

  • This only works within a web application, for classes (entities) deployed in WEB-INF/classes. This is because the enhancer will attempt to overwrite the original *.class files with the enhanced *.class files. If your application server explodes the EAR into a directory structure, this will succeed. If the original classes were bundled in a *.jar file, then the enhancement will fail on write. Consequently, ejb-jars or utility jars within the EAR can not be enhanced at runtime.
  • Make sure the enhancement process has sufficient file permissions to write into WEB-INF/classes and its content. Sounds obvious if you think of it. Costs hours debugging if you don’t.

Conclusion: There is a way to implement runtime ‘enhancement’ for Datanucleus.  No change to the build process is required. It is limited to the web module of a JEE application, but allows to introduce the beauty of JDO/Datanucleus in the most non-invasive way. Hopefully, the enhancement process will be improved to support enhancement on the fly, without the attempt to overwrite *.class files. This would allow to use JEE structures where entities reside within a separate ejb module…

Runtime Enhancement with JDO and Datanucleus