How to Install AWS JAVA SDK in Ubuntu 16.04


In this post, I write the installation for AWS JAVA SDK. I followed this documentation 


1. Install the latest Oracle JAVA JDK.


I need to download "Oracle JAVA JDK" from here. I will install the JDK. JDK includes the JRE. In my case, I create "javase" directory where I download and extract downloaded file on. And I used "wget" command with options "--no-check-certificate" to obtain from download link.


# mkdir javase

# cd javase

wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/10.0.2+13/19aef61b38124481863b1413dce1855f/jdk-10.0.2_linux-x64_bin.tar.gz 


# tar xvfz jdk-10.0.2_linux-x64_bin.tar.gz


The extracted files are not for installation. They are the files to run and use. Therefore, I need to edit my ".bashrc". In my case, "java" and "javac" files are located in "/home/ubuntu/javase/jdk-10.0.2/bin". 


cat /home/ubuntu/.bashrc

# export PATH=$PATH:/home/ubuntu/javase/jdk-10.0.2/bin

source /home/ubuntu/.bashrc


Now, I can use the Oracle JDK. "java --version" show the version information.

 

# java --version

java 10.0.2 2018-07-17

Java(TM) SE Runtime Environment 18.3 (build 10.0.2+13)

Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.2+13, mixed mode)


And I also create sample code, "sample.java", in different directory. In my case, I create another directory which name is "projects". I write like below.   


# mkdir -p /home/ubuntu/projects

# vi Sample.java

package com.sample;


class Sample {

     public static void main(String[] args){

           System.out.println("Hello, JAVA");

     }

}


And compile and run the sample code, "javac -d . Sample.java". I used option "-d" because I defined the package in the sample code. After compile, I can confirm "Sample.class" file is located on that directory. And Run it.


# javac -d . Sample.java

# ls com/sample/Sample.class

com/sample/Sample.class


# java com/sample/Sample

Hello, JAVA


Now, I can do JAVA programming.


2. Set up for the AWS SDK.


I still can not use the AWS SDK, now. In this part, I will follow some instruction to setup for the AWS SDK. In this documentation, I need to choose builder, In my case I select "Apache Maven". To use the SDK with Apache Maven, I need to have Maven installed.


2-1. Download, Install and Run Maven


I follow in this documentation. I make directory for Maven, And Download and extract it.


# mkdir apache-mavena

# cd apache-mavena

# wget http://apache.tt.co.kr/maven/maven-3/3.5.4/binaries/apache-maven-3.5.4-bin.tar.gz

tar xvfz apache-maven-3.5.4-bin.tar.gz

 

In my case, "bin" is located in "/home/ubuntu/apache-maven/apache-maven-3.5.4/bin". I will add this path in my ".bashrc" file.


cat /home/ubuntu/.bashrc

export PATH=$PATH:~/.local/bin:/home/ubuntu/javase/jdk-10.0.2/bin:/home/ubuntu/apache-maven/apache-maven-3.5.4/bin

source /home/ubuntu/.bashrc


Now, I can confirm the version for marven with "mvn -v" command


# mvn -v

Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-17T18:33:14Z)

Maven home: /home/ubuntu/apache-maven/apache-maven-3.5.4

Java version: 10.0.2, vendor: Oracle Corporation, runtime: /home/ubuntu/javase/jdk-10.0.2

Default locale: en_US, platform encoding: UTF-8

OS name: "linux", version: "4.4.0-1066-aws", arch: "amd64", family: "unix"


I think I prepare to use this. I will follow the rest of the instructions. 


2-2. Create a new Maven package


In this documentation, it shows Maven Archetype. I think this is similar with "create projects" of other program languages. 


# cd projects/

# mvn -B archetype:generate \

  -DarchetypeGroupId=org.apache.maven.archetypes \

  -DgroupId=com.sample.myapps \

  -DartifactId=app


[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 54.510 s
[INFO] Finished at: 2018-09-12T21:02:15Z
[INFO] ------------------------------------------------------------------------

# ls -la app/
total 16
drwxr-xr-x 3 root root 4096 Sep 12 21:02 .
drwxr-xr-x 3 root root 4096 Sep 12 21:02 ..
-rw-r--r-- 1 root root  636 Sep 12 21:02 pom.xml
drwxr-xr-x 4 root root 4096 Sep 12 21:02 src


After run command above, I can see the "app" directory. In this directory, "pom.xml" and "src" directory are located. And I also can confirm there is "App.java" file under "/src/main/java/com/sample/myapps". To use the AWS SDK for Java in my project, I need to declare it in "pom.xml" file. In my case, I want to entire AWS SDK. Therefore I will add like below. (I can see the latest version in this document


# vi app/pom.xml

  <dependencies>

    <dependency>

      ....................

    </dependency>

    <dependency>

      <groupId>com.amazonaws</groupId>

      <artifactId>aws-java-sdk</artifactId>

      <version>1.11.407</version>

    </dependency>

  </dependencies>

</project>

ckag


Now, I configure to use AWS entire SDK. I can build if my configuration is correct or not with "mvn package". This command is for building the project.


# cd app/

# mvn package


After run command, I can see the AWS SDK downloaded. Please, note, you can meet some error "Source option 5 is no longer supported. Use 6 or later." and build fail. I solved this issue with adding 


# vi pom.xml

  <properties>

    <maven.compiler.source>1.6</maven.compiler.source>

    <maven.compiler.target>1.6</maven.compiler.target>

  </properties>


Now. Let's try to make some code. However, I have some question. "where is the main function to start coding?". In my case, main file is located in "./app/src/main/java/com/sample/myapps/App.java". Look at the this file.

vi app/src/main/java/com/sample/myapps/App.java

package com.sample.myapps;


/**

 * Hello world!

 *

 */

public class App

{

    public static void main( String[] args )

    {

        System.out.println( "Hello World!" );

    }

}



I have already built with this source. I can see the "class" file in the "/target/classes".

ls app/target/classes/com/sample/myapps/App.class

app/target/classes/com/sample/myapps/App.class


Thus, I can run this file. But I do not know how it is possible with command. 

mvn exec:java -Dexec.mainClass=com.sample.myapps.App


INFO] --- exec-maven-plugin:1.2.1:java (default-cli) @ app ---

Hello World!

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS


Look!, I get the result. It's works now. If you meet some error, please do mvn with "clean" and "compile" again.

mvn clean

# mvn compile


I used "mvn exec:java -Dexec.mainClass=com.sample.myapps.App" command with some option. It is not simple to re-write. Therefore, I can add some plugin in the pom.xml. I add "<build><plugins></plugins></build>"

# cat pom.xml

<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.sample.myapps</groupId>

  <artifactId>app</artifactId>

  <packaging>jar</packaging>

  <version>1.0-SNAPSHOT</version>

  <name>app</name>

  <url>http://maven.apache.org</url>

  <properties>

    <maven.compiler.source>1.6</maven.compiler.source>

    <maven.compiler.target>1.6</maven.compiler.target>

  </properties>

  <dependencies>

    ........................................................

  </dependencies>

  <build>

    <plugins>

    <plugin>

        <groupId>org.codehaus.mojo</groupId>

        <artifactId>exec-maven-plugin</artifactId>

        <version>1.2.1</version>

        <executions>

            <execution>

                <goals>

                    <goal>java</goal>

                </goals>

            </execution>

        </executions>

        <configuration>

            <mainClass>com.sample.myapps.App</mainClass>

        </configuration>

    </plugin>

    </plugins>

  </build>

</project>


Now I can run without the option.

mvn exec:java



In this documentation, this shows 5 ways to obtain the credential. 

1. Environment variables–AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. 
2. Java system properties–aws.accessKeyId and aws.secretKey. 
3. The default credential profiles file– typically located at ~/.aws/credentials 
4. Amazon ECS container credentials
5. Instance profile credentials

These method has different class each to use. In this documentation, it shows how to setup for 1 and 3 above. I will use the "S3 list bucket" as sample code for this test. The sameple code is here. I copied and pasted in App.java.

vi src/main/java/com/sample/myapps/App.java

package com.sample.myapps;


import com.amazonaws.services.s3.AmazonS3;

import com.amazonaws.services.s3.AmazonS3ClientBuilder;

import com.amazonaws.services.s3.model.Bucket;

import java.util.List;


public class App

{

    public static void main( String[] args )

    {

        final AmazonS3 s3 = AmazonS3ClientBuilder.defaultClient();

        List<Bucket> buckets = s3.listBuckets();

        System.out.println("Your Amazon S3 buckets are:");

        for (Bucket b : buckets) {

           System.out.println("* " + b.getName());

        }

    }

}


# mvn clean compile

# mvn exec:java


Someone can get some error like below. There are several reasons. One of reasons is "credential" issue. Thus, my application does not get the correct credential information.

"InvocationTargetException: Failed to parse XML document with handler class com.amazonaws.services.s3.model.transform.XmlResponsesSaxParser$ListAllMyBucketsHandler: The entity "ntilde" was referenced, but not declared."

Look at this documentation. I think my sample code try to use environment variable. So I need to export some parameters like below.

export AWS_ACCESS_KEY_ID=xxxxxx

# export AWS_SECRET_ACCESS_KEY=xxxx

# export AWS_REGION=ap-northeast-2


After add this values, run "mvn exec:java". I can get finally the results.

mvn exec:java

Your Amazon S3 buckets are:

* cf-templates-16hzoxi2ozb3b-ap-northeast-1


At this time, I try to run with "~/.aws/credential" and "~/.aws/config". I add "[s3with]" on each like below. To use this profile, I need to export some values. I can see the some error messages like "InvocationTargetException: profile file cannot be null ".

# vi ~/.aws/credentials

[default]

aws_access_key_id=xxxxx

aws_secret_access_key=xxxxxxx


[s3with]

aws_access_key_id=yyyyyy

aws_secret_access_key=yyyyy


# vi ~/.aws/config

[default]

region=zzzzz


[s3with]

region=ap-northeast-2


# export AWS_PROFILE=s3with

# export AWS_CREDENTIAL_PROFILES_FILE=/home/ubuntu/.aws/credentials


Now, I need revise sample code. Please, note, I import more, "import com.amazonaws.auth.profile.ProfileCredentialsProvider;" and "import com.amazonaws.regions.Regions;".

## cat src/main/java/com/sample/myapps/App.java

package com.sample.myapps;


import com.amazonaws.services.s3.AmazonS3;

import com.amazonaws.services.s3.AmazonS3ClientBuilder;

import com.amazonaws.services.s3.model.Bucket;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;

import com.amazonaws.regions.Regions;

import java.util.List;


public class App

{

    public static void main( String[] args )

    {

        final AmazonS3 s3 = AmazonS3ClientBuilder.standard()

                        .withRegion(Regions.AP_NORTHEAST_2)

                        .withCredentials(new ProfileCredentialsProvider("s3with"))

                        .build();

        List<Bucket> buckets = s3.listBuckets();

        System.out.println("Your Amazon S3 buckets are:");

        for (Bucket b : buckets) {

           System.out.println("* " + b.getName());

        }

    }

}


Now, Also I can get the results again. Another method is insert the credential into the code with "BasicAWSCredentials" and "AWSStaticCredentialsProvider"

import com.amazonaws.auth.BasicAWSCredentials;

import com.amazonaws.auth.AWSStaticCredentialsProvider;


And the sample code should be re-write like below.

# cat src/main/java/com/sample/myapps/App.java

package com.sample.myapps;


import com.amazonaws.services.s3.AmazonS3;

import com.amazonaws.services.s3.AmazonS3ClientBuilder;

import com.amazonaws.services.s3.model.Bucket;

import com.amazonaws.auth.BasicAWSCredentials;

import com.amazonaws.auth.AWSStaticCredentialsProvider;

import java.util.List;


public class App

{

    public static void main( String[] args )

    {

        BasicAWSCredentials awsCreds = new BasicAWSCredentials("xxxxx", "xxxxx");

        final AmazonS3 s3 = AmazonS3ClientBuilder.standard()

                        .withRegion(Regions.AP_NORTHEAST_2)

                        .withCredentials(new AWSStaticCredentialsProvider(awsCreds))

                        .build();

        List<Bucket> buckets = s3.listBuckets();

        System.out.println("Your Amazon S3 buckets are:");

        for (Bucket b : buckets) {

           System.out.println("* " + b.getName());

        }

    }

}


So far, I use profile for Credentials. And I use the static method for Region. I am some question for this. Is there anyway to use the profile for this Region field. "AwsProfileRegionProvider;" class offer it.


## cat src/main/java/com/sample/myapps/App.java

package com.sample.myapps;


import com.amazonaws.services.s3.AmazonS3;

import com.amazonaws.services.s3.AmazonS3ClientBuilder;

import com.amazonaws.services.s3.model.Bucket;


import com.amazonaws.auth.profile.ProfileCredentialsProvider;

import com.amazonaws.regions.AwsProfileRegionProvider;

import java.util.List;


public class App

{

    public static void main( String[] args )

    {


        AwsProfileRegionProvider r = new AwsProfileRegionProvider("s3with");

        String rs = r.getRegion();


        final AmazonS3 s3 = AmazonS3ClientBuilder.standard()

                        .withRegion(rs)

                        .withCredentials(new ProfileCredentialsProvider("s3with"))

                        .build();

        List<Bucket> buckets = s3.listBuckets();

        System.out.println("Your Amazon S3 buckets are:");

        for (Bucket b : buckets) {

           System.out.println("* " + b.getName());

        }


    }

}


# mvn clean compile

# mvn exec:java


So, Now, I can get the information about credential and reason with the profile. Please, note, I have define the information on "credentials" and "config". I need to add some Environment like below.


export AWS_CONFIG_FILE=/home/ubuntu/.aws/config 

# export AWS_CREDENTIAL_PROFILES_FILE=/home/ubuntu/.aws/credentials


If I am necessary, I can add these over my ".bashrc" file. Now, Enjoy the JAVA coding.



Reference 


[ 1 ] https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/setup-install.html

[ 2 ] https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/setup-project-maven.html

[ 3 ] https://maven.apache.org/index.html

[ 4 ] http://maven.apache.org/archetypes/maven-archetype-quickstart/

[ 5 ] https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-bom

[ 6 ] https://github.com/spring-guides/gs-maven/issues/21

[ 7 ] https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html

[ 8 ] https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/setup-credentials.html

[ 9 ] https://stackoverflow.com/questions/19850956/maven-java-the-parameters-mainclass-for-goal-org-codehaus-mojoexec-maven-p

[ 10 ] https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/index.html?com/amazonaws/auth/profile/ProfileCredentialsProvider.html

+ Recent posts