Deploy Java Lambda using SAM and Buildkite

I’ve recently covered how to deploy a Node JS based Lambda using SAM and Buildkite. I would say that this should cover most use cases, since I believe a majority of AWS Lambdas are implemented with JavaScript.

However, Lambda supports many more programming languages than just JavaScript and one of the more important ones among them is certainly Java. In principle, deployment for Java and JavaScript is very similar: we provide a SAM template and an archive of a packaged application. However, Java uses a different toolset than JavaScript, so the build process of the app will be different.

In the following, I will briefly explain how to build and deploy a Java Lambda using Maven, SAM and Buildkite. If you want to get to the code straight away, find a complete sample project here:

https://github.com/mxro/lambda-java-sam-buildkite

First we define a simple Java based Lambda:

package com.amazonaws.handler;

import com.amazonaws.services.lambda.runtime.Context; 
import com.amazonaws.services.lambda.runtime.LambdaLogger;

public class SimpleHandler {
    public String myHandler(int myCount, Context context) {
        LambdaLogger logger = context.getLogger();
        logger.log("received : " + myCount);
        return String.valueOf(myCount);
    }
}

Then add a pom.xml to define the build and dependencies of our Java application:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.amazonaws</groupId>
    <artifactId>lambda-java-sam-buildkite</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>
    <name>Sample project for deploying a Java AWS Lambda function using SAM and Buildkite.</name>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.plugin.version>3.8.0</maven.compiler.plugin.version>
        <aws.lambda.java.core.version>1.1.0</aws.lambda.java.core.version>
        <junit.version>4.12</junit.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-lambda-java-core</artifactId>
            <version>${aws.lambda.java.core.version}</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>    
    </dependencies>

    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven.compiler.plugin.version}</version>
                <configuration>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    
</project>

We define the lambda using a SAM template. Note that we are referencing the JAR that is assembled using Maven target/lambda-java-sam-buildkite-1.0.0.jar.

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
    sam-app

Globals:
    Function:
        Timeout: 20
        Environment: 

Resources:
  SimpleFunction:
    Type: AWS::Serverless::Function 
    Properties:
      CodeUri: target/lambda-java-sam-buildkite-1.0.0.jar
      Handler: com.amazonaws.handler.SimpleHandler::myHandler
      Runtime: java8

Then we need Dockerfile that will run our build. Here we simply start with an image that has Maven preinstalled and then install Python and the AWS SAM CLI.

FROM zenika/alpine-maven:3-jdk8

# Installing python
RUN apk add --update \
    python \
    python-dev \
    py-pip \
    build-base \
  && pip install virtualenv \
  && rm -rf /var/cache/apk/*

RUN python --version

# Installing AWS CLI and SAM CLI
RUN apk update && \
    apk upgrade && \
    apk add bash && \
    apk add --no-cache --virtual build-deps build-base gcc && \
    pip install awscli && \
    pip install aws-sam-cli && \
    apk del build-deps

RUN mkdir /app
WORKDIR /app
EXPOSE 3001

The following build script will run within this Dockerfile and first package the Java application into a Jar file using mvn package and then uses the SAM CLI to deploy the template and application.

#!/bin/bash -e

mvn package

echo "### SAM Deploy"

sam --version

sam package --template-file template.yaml --s3-bucket sam-buildkite-deployment-test --output-template-file packaged.yml

sam deploy --template-file ./packaged.yml --stack-name sam-buildkite-deployment-test --capabilities CAPABILITY_IAM

Finally we define the Buildkite template. Note that this template assumes the environment variables AWS_DEFAULT_REGION, AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are provided by Buildkite.

steps:
  - name: Build and deploy to AWS
    command:
      - './.buildkite/deploy.sh'
    plugins:
      - docker-compose#v2.1.0:
          run: app
          config: 'docker-compose.yml'
          env:
            - AWS_DEFAULT_REGION
            - AWS_ACCESS_KEY_ID
            - AWS_SECRET_ACCESS_KEY

Now we simply need to create a Buildkite pipeline and link it to a repository with our source code.

A Handy Reference of Maven Parameters

I cannot count the times I have looked up the following through Google. Thus I decided to put together a few handy parameters (or properties or whatever is the correct term) for Maven builds.

All the below are given with the goal install but they can safely be used with any other Maven goal as well.

Skip Tests

mvn install -DskipTests

Build Only From Specified Project

This is only relevant in a multi pom.

mvn install -rf :[artifactId]

Don’t Compile JavaDoc

-Dmaven.javadoc.skip=true

Don’t Compile GWT

-Dgwt.compiler.skip=true

 

Installing Jenkins on Centos 7

I set up a Jenkins server on a brand new Centos 7 VPS. In the following the instructions for doing this in case you are looking at doing the same:

Setting up Jenkins Server

sudo yum install java-1.8.0-openjdk
sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
sudo rpm --import https://jenkins-ci.org/redhat/jenkins-ci.org.key
sudo yum install jenkins

Or for stable version (link did not work for me when I tried it)

sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
yum install jenkins
  • Start Jenkins server
sudo systemctl start jenkins

You should now be able to access Jenkins at yourserver.com:8080 (if not, see troubleshooting steps at the bottom).

If you want to access your server more securely on port 80, you can do so by installing ngnix as outlined in this article in step 4: How to Install Jenkins on CentOS 7.

Connecting to a Git Repo

You will probably want to connect to a git repository next. This is also somewhat dependent on the operating system you use, so I provide the steps to do this on CentOS as well:

  • Install git
sudo yum install git
  • Generate an SSH key on the server
ssh-keygen -t rsa
  • When prompted, save the SSH key under the following path (I got this idea from reading the comments here)
/var/lib/jenkins/.ssh
  • Assure that the .ssh directory is owned by the Jenkins user:
sudo chown -R jenkins:jenkins /var/lib/jenkins/.ssh
  • Copy the public generated key to your git server (or add it in the GitHub/BitBucket web interface)
  • Assure your git server is listed in the known_hosts file. In my case, since I am using BitBucket my /var/lib/jenkins/.ssh/known_hosts file contains something like the following
bitbucket.org,104.192.143.3 ssh-rsa [...]
  • You can now create a new project and use Git as the SCM. You don’t need to provide any git credentials. Jenkins pulls these automatically form the /var/lib/jenkins/.ssh directory. There are good instructions for this available here.

Connecting to GitHub

  • In the Jenkins web interface, click on Credentials and then select the Jenkins Global credentials. Add a credential for GitHub which includes your GitHub username and password.
  • In the Jenkins web interface, click on Manage Jenkins and then on Configure System. Then scroll down to GitHub and then under GitHub servers click the Advanced Button. Then click the button Manage additional GitHub actions.

additional actions

  • In the popup select Convert login and password to token and follow the prompts. This will result in a new credential having been created. Save and reload the page.
  • Now go back to the GitHub servers section and now click to add an additional server. As credential, select the credential which you have just selected.
  • In the Jenkins web interface, click on New Item and then select GitHub organisation and connect it to your user account.

Any of your GitHub projects will be automatically added to Jenkins, if they contain a Jenkinsfile. Here is an example.

Connect with BitBucket

  • First, you will need to install the BitBucket plugin.
  • After it is installed, create a normal git project.
  • Go to the Configuration for this project and select the following option:

BitBucket trigger

  • Log into BitBucket and create a webhook in the settings for your project pointing to your Jenkins server as follows: http://youserver.com/bitbucket-hook/ (note the slash at the end)

Testing a Java Project

Chances are high you would like to run tests against a Java project, in the following, some instructions to get that working:

Troubleshooting

  • If you cannot open the Jenkins web ui, you most likely have a problem with your firewall. Temporarily disable your firewall with: `sudo systemctl stop iptables` and see if it works then.
  • If it does, you might want to check your rules in `/etc/sysconfig/iptables` and assure that port 8080 is open
  • Check the log file at:
sudo cat /var/log/jenkins/jenkins.log

 

Generate md5 Hash for Maven

Maven creates and checks MD5 checksums at various times. For instance, when downloading an artifact from a repository, Maven checks whether the checksum of the downloaded files (e.g. POM, JAR) is correct.

I am uploading Maven artifacts manually to a very simple, file-based repository. This requires me to calculate the Maven checksum for artifacts manually.

What sounds like a simple problem at first actually turned out to be quite tricky (as it often does with Maven? Well, I guess it’s still better than regular expressions!).

After digging around in the project checksum-maven-plugin, I finally figured out how to generate MD5 checksum files in a way that Maven will accept. The key here was to use the Hex class from Bouncy Castle to turn the MD5 digest into a String.

Following the rough-cut code to create a hash file for Maven (extracted from the maven-tools project, class WriteHashes):

public static void writeMd5(final Path baseFile) throws NoSuchAlgorithmException, IOException {
        final FileInputStream fis = new FileInputStream(baseFile.toFile());

        final MessageDigest messageDigest = MessageDigest.getInstance("MD5");
        messageDigest.reset();
        final byte[] buffer = new byte[1024];
        int size = fis.read(buffer, 0, 1024);
        while (size >= 0) {
            messageDigest.update(buffer, 0, size);
            size = fis.read(buffer, 0, 1024);
        }

        final String result = new String(Hex.encode(messageDigest.digest()));

        fis.close();

        final Path md5File = baseFile.getFileSystem().getPath(baseFile.toString() + ".md5");

        FilesJre.wrap(md5File.toFile()).setText(result);
    }

Setting Up Xtend with Maven and eclipse (Luna)

Xtend is currently my favourite alternative language for the JVM (closely followed by Kotlin). Unfortunately, I did not find a good guide of how to set up a Maven project within eclipse (Luna) which uses Xtend.

Specifically the following guide will allow you to allow you to write test cases in Xtend for your existing Java projects. A great way to get started with Xtend I suppose.

The following describes the necessary steps.

  • Install the Xtend plugin for eclipse as described here.
  • Add the xtend-maven-plugin to your pom.xml as follows:
<plugin>
    <groupId>org.eclipse.xtend</groupId>
    <artifactId>xtend-maven-plugin</artifactId>
    <version>2.7.1</version>
    <executions>
        <execution>
            <goals>
                <goal>testCompile</goal>
            </goals>

            <configuration>
                <testOutputDirectory>${basedir}/src/test/java</testOutputDirectory>
            </configuration>

        </execution>
    </executions>
</plugin> 
  • Also add a dependency to the Xtend runtime libraries
<dependency>
    <groupId>org.eclipse.xtend</groupId>
    <artifactId>org.eclipse.xtend.lib</artifactId>
    <version>2.7.1</version>
    <scope>test</scope>
</dependency>
  • Right click the project and select Maven / Update Project … and update the project.
  • Right clock the project and select Properties
  • Go to the Xtend / Compiler page
  • Set as the ouput director src/test/java

  • Go to the folder src/test/xtend. If the folder does not exist, create it.
  • Right clock the folder src/test/xtend and select Build Path / Use As Source Folder
  • Create a package in the new src/test/xtend folder and right click the package. Select New / Xtend class and define a class such as the following:
package de.mxro.async.map.tests
 

import org.junit.Assert
import org.junit.Test
 

class TestThatNumbersAreEqual {
    
    @Test
    def void test() {
        Assert.assertTrue(3 == 3)
    }
    
    
}
  • Immediately after you save the class a translated class should be created in the folder src/test/java

Now, have fun writing tests using Xtend’s concise syntax – while not affecting any step of your build and development workflow!

To see an example configuration in a complete project, also check out async-map on GitHub.

Setting Up eclipse Luna with Maven for Android

As of August 2014, don’t even try this.

Officially, the Google Eclipse plugin supports Eclipse 4.4 (Luna) at present. However, in order to be able to create projects which are both Maven projects and Android projects you will need to install the m2e-android plugin. This currently does not support eclipse Luna. Probably, if you create a new Android project based on the archetype suggested by the m2e-android plugin, you might get errors such as:

  • …R cannot be resolved to a variable
  • Plugin execution not covered by lifecycle configuration: com.jayway.maven.plugins.android.generation2:android-maven-plugin:3.8.2:generate-sources (execution: default-generate-sources, phase: generate-sources)
  • Project configurator “me.gladwell.eclipse.m2e.android.androidDevelopmentToolsProjectConfigurator” is not available. To enable full functionality, install the project configurator and run Maven->Update Project Configuration.
  • Plugin execution not covered by lifecycle configuration: com.jayway.maven.plugins.android.generation2:android-maven-plugin:3.8.2:proguard (execution: default-proguard, phase: process-classes)

My recommendation is to use Android Studio.

You can easily add Maven dependencies to projects in Android Studio. Just locate the ‘build.gradle’ file in your application directory and add a compile dependency.

Jenkins StackOverflow Exception during JUnit Test

Problem

The build of a Maven job in Jenkins fails due to a StackOverflowException or a OutOfMemoryException during a JUnit test.

Analysis

Most likely, there is a bug in your application, which leads to infinite recursion or an infinite allocation in resources. So first try to run your test in a different environment (for instance in eclipse, directly through Maven or as plain Java application).

However, sometimes, as in my case, the application works correctly and just requires more memory/stack size than is provided by the JVM during default settings. In this case, you will need to adjust the JVM settings in order to allow for more memory/stack size.

Solution

The JVM parameters, which allow to allocate more memory or stack size to a JVM are:

1. 

-Xss(x)m

where x is the size of the stack you would like to use. For instance: -Xss4m for a 4 MB stack size.

2.

-Xmx(x)m

where x is the size of the Java heap space (=memory) you would like to use. For instance: -Xmx1024m for a 1024 MB heap space.

Unfortunately, there are multiple places in which these parameters can be configured. Essentially, if the increased heap space requirement is in your application, you will need to adjust the parameters for the JUnit test runner in Maven:


<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-surefire-plugin</artifactId>
 <version>2.12.4</version>
 <configuration>
 <argLine>-Xss18m</argLine>
 </configuration>
 </plugin>

However, if the adjusted parameters are required for building your application, you might have to adjust them for the Maven Build Process.

This can be done by adding the parameters to MAVEN_OPTS either:

  • for your job: [Your Job] / Configure / Build / Advanced / MAVEN_OPTS
  • or for the Jenkins instance: Jenkins / Manage Jenkins / Configure System / Maven Project Configuration / Global MAVEN_OPTS

The last possible culprit might be the Jenkins server itself.

You can set the JVM parameters for Jenkins either by specifying them when:

  • starting Jenkins through java [your JVM parameters here] -jar jenkins.war or
  • by editing the jenkins.xml in your JENKINS_HOME folder.

Resources

Increasing Memory of junit Testcases

Stackoverflow – Jenkins build fails after running Cucumber tests on Java heap space exception

Increase heap size in java

Stackoverflow – How to give Jenkins more heap space when it´s started as a service under Windows?

 

Maven Module for gwt-exporter

gwt-exporter is an awesome library to generate usable JavaScript APIs for Google Web Toolkit applications.

It allows writing powerful libraries in Java and reuse the features these libraries provide in JavaScript applications!

I have assembled a small Maven Module for gwt-exporter 2.4 (M1), which readily configures gwt-exporter to be used as part of an OSGi-enabled project. This is particularily useful, if one wants to develop using the excellent eclipse plug-in development platform (which is useful for far more than developing eclipse plugins).

The source code is hosted as part of the osgi-maven project: thrdGwtExporter24.

The Maven dependency and repository are as follows:

Dependency:


 <dependency>
 <groupId>de.mxro.thrd.gwtexporter24</groupId>
 <artifactId>thrdGwtExporter24</artifactId>
 <version>0.0.1</version>
 </dependency>

Repository:


<repositories>
 <repository>
 <id>onedb Releases</id>
 <url>http://dl.dropbox.com/u/957046/onedb/mvn-releases</url>
 </repository>
</repositories>

If you would like to use gwt-exporter in a vanilla Maven project (without OSGi), you can use the gwt-exporter artefact hosted on Maven central:


<dependency>
 <groupId>org.timepedia.exporter</groupId>
 <artifactId>gwtexporter</artifactId>
 <version>2.4.0-M1</version>
 <scope>provided</scope>
 <exclusions>
<exclusion>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
</exclusion>
 </exclusions>
</dependency>

(The exclusion is necessary to avoid dependencies to the Sun/Oracle JVM.)

Restlet Quickstart

The Restlet framework is one of the possible options to provide Restful web services in Java. In many framework comparison, Restlet is criticized for being a little bit difficult to understand as well as to perform slightly worse than competing frameworks (e.g. Apache Wink, Jersey, …) (Sangeetha, 2011). However, Restlet is also a very flexible framework and it is very lightweight, in that it has very few dependencies to heavyweight components, for instance servlet containers. This enables Restlet to play nicely with a number of technologies including Google Android, Google App Engine and Google Web Toolkit applications.

The tutorials on the Restlet homepage appear to be a bit confusing and outdated. Therefore, I have assembled a little example to get started with Restlet in a few traceable steps.

Add Maven Dependency

Restlet offers a wealth of different editions and optional extensions and it is a little bit difficult to determine the right Maven dependencies. For this basic scenario, we want to run a little server deployed as local Java application. For this purpose, the ext.simple extension is required (here I use the latest milestone release 2.1-M7 – the examples should also work with later releases although this is not guaranteed)


<dependency>

<groupId>org.restlet.jse</groupId>

<artifactId>org.restlet</artifactId>

<exclusions>

<exclusion>

<groupId>org.osgi</groupId>

<artifactId>org.osgi.core</artifactId>

</exclusion>

</exclusions>

<version>2.1-M7</version>

</dependency>

<dependency>

<groupId>org.restlet.jse</groupId>

<artifactId>org.restlet.ext.simple</artifactId>

<version>2.1-M7</version>

</dependency>

In addition, the Restlet repository must be specified


<repositories>
<repository>
<id>maven-restlet</id>
<name>Public online Restlet repository</name>
<url>http://maven.restlet.org</url>
</repository>
</repositories>

<span style="color: black;">

Create a Small Standalone Server

If these dependencies are established, the following server can be implemented:


import org.restlet.Component;
import org.restlet.data.Protocol;
import org.restlet.resource.Get;
import org.restlet.resource.ServerResource;
import org.restlet.routing.Router;

public class RestletServerTest extends ServerResource {

public static void main(final String[] args) throws Exception {
// Create a new Component.
final Component component = new Component();

// Add a new HTTP server listening on port 8182.
component.getServers().add(Protocol.HTTP, 8182);

final Router router = new Router(component.getContext().createChildContext());

router.attach("/test", RestletServerTest.class);

// Attach the sample application.
component.getDefaultHost().attach("/restlet", router);

// Start the component.
component.start();
}

@Override
@Get
public String toString() {
return "hello, world";
}

}

Execute this application and open http://localhost:8182/restlet/test. You should see the message ‘hello, world’.

Provide a Domain Object

In order to provide a domain object, a few more steps need to be undertaken. First, we need to specify the domain object:


import java.io.Serializable;

public class Person implements Serializable {

private static final long serialVersionUID = 1L;

public String name;
public int age;

public Person(final String name, final int age) {
super();
this.name = name;
this.age = age;
}

}

Secondly, we need an interface and a ServerResource implementation for the service, which provides the domain object. The interface does not need to extend any other interface but must use the GET, PUT, DELETE annotations provided by Restlet.


import org.restlet.resource.Get;

public interface PersonResource  {

@Get
public Person retrieve();

}
<pre>

The ServerResource implementation must extend ServerResource and implement the interface PersonResource:


import org.restlet.resource.ServerResource;

public class PersonServerResource extends ServerResource implements PersonResource {

private static volatile Person person1 = new Person("Peter", 40);

@Override
public Person retrieve() {

return person1;
}

}
<pre>

Finally, the main routine starting the server needs to be altered. Also, a little client is added, which reads out the domain object from the server:


import org.restlet.Component;
import org.restlet.data.Protocol;
import org.restlet.resource.ClientResource;
import org.restlet.routing.Router;

public class RestletServerTest  {

public static void main(final String[] args) throws Exception {
// Create a new Component.
final Component component = new Component();

// Add a new HTTP server listening on port 8182.
component.getServers().add(Protocol.HTTP, 8182);

final Router router = new Router(component.getContext().createChildContext());

router.attach("/person", PersonServerResource.class);

// Attach the sample application.
component.getDefaultHost().attach("/restlet", router);

// Start the component.
final Thread t = new Thread() {

@Override
public void run() {
try {
component.start();
} catch (final Exception e) {
e.printStackTrace();
}
super.run();
}

};

t.run();

final ClientResource cr = new ClientResource("http://localhost:8182/restlet/person");

final PersonResource resource = cr.wrap(PersonResource.class);
final Person person = resource.retrieve();

System.out.println(person.name);

}

}
<pre>

The domain object is serialized using the Java Serialization mechanism. We can also navigate to http://localhost:8182/restlet/person using a web browser. However, only a binary file will be downloaded by the server. Restlet does provide extensions to provide the domain objects serialized as in RDF, XML and JSON format.

Emulate a RPC Call Using Domain Objects

Apart from reading domain (and writing using PUT) domain objects, Restlet can easily be used to implement a kind of remote procedure calls (RPC) or functionality similar to Java Remote Method Invocation (RMI). Such calls being made over Restlet do not only have the advantage of running cleanly over HTTP but are also rather performant when compared to remote invocations building on XML serializations (Java Serialization, although slow, is often faster than XML Serialization) such as used by XML-RPC or SOAP/WDSL based web services.

First we change the PersonResource Service description and define a POST service, which makes a copy of a person object.

import org.restlet.resource.Post;

public
interface PersonResource {

@Post
public Person copy(Person p);

    

}

Next we change the implementation of the service:

import org.restlet.resource.ServerResource;

public
class PersonServerResource extends ServerResource implements PersonResource {

    

    @Override

    public Person copy(final Person p) {

        return p;

    }

    

}

And finally change the main method. Note here too that here we run the server and client as part of a unit test (so add JUnit dependency to your pom). This highlights how easy it is to build (almost) fully blown integration tests based on Restlet, which in addition execute very fast.


import org.junit.Assert;
import org.junit.Test;
import org.restlet.Component;
import org.restlet.data.Protocol;
import org.restlet.resource.ClientResource;
import org.restlet.routing.Router;

public class RestletServerTest  {

@Test
public void test_server() throws Exception {
// Create a new Component.
final Component component = new Component();

// Add a new HTTP server listening on port 8182.
component.getServers().add(Protocol.HTTP, 8182);

final Router router = new Router(component.getContext().createChildContext());

router.attach("/person", PersonServerResource.class);

// Attach the sample application.
component.getDefaultHost().attach("/restlet", router);

// Start the component.
final Thread t = new Thread() {

@Override
public void run() {
try {
component.start();
} catch (final Exception e) {
e.printStackTrace();
}
super.run();
}

};

t.run();

final ClientResource cr = new ClientResource("http://localhost:8182/restlet/person");

final PersonResource resource = cr.wrap(PersonResource.class);
final Person originalPerson = new Person("Peter", 20);
final Person copiedPerson = resource.copy(originalPerson);

Assert.assertFalse(originalPerson == copiedPerson);

Assert.assertTrue(originalPerson.name.equals(copiedPerson.name));

System.out.println(copiedPerson.name);

}

}
<pre>

Resources

Restlet Documentation Hello World Application in JavaSE

Maven and Eclipse Indigo

It has been a while since the new release of the eclipse IDE, Indigo, has been released. One of the most interesting new features seems to be a better integration with Maven.

After some very unsuccessful attempts using eclipse IAM and the m2eclipse plugin, I became a bit sceptical of Maven integration into the eclipse IDE. In particular, I want to use the eclipse plugin development environment (PDE) alongside Maven, which seemed impossible at the time. At the moment, I use the eclipse:eclipse Maven Mojo to generate eclipse project files (with PDE support). The projects compile in eclipse and unit test etc run. Just for any Maven specific tasks, I need to change to the command line (eg deploying projects, changing dependencies between projects).

Now I have seen a few negative comments about the new Maven features in eclipse (see below). After spending a lot of time getting eclipse PDE and Maven working together well, I feel a bit anxious to change to eclipse Indigo.

Resources

Changing from m2eclipse to m2e (Eclipse 3.7 – Indigo)

Maven and Eclipse, Top Eclipse Indigo Feature #10 (critique in the comments)