How to get current date time with Java 8

 In this quick tutorial, we will see, how to get current date time using Java 8.


Java 8 had come up with new set of classes for date and time under java.time package, which are :

-  java.time.Instant

- java.time.ZonedDateTime

- java.time.OffSetDateTime

- java.time.LocalDateTime

Let us see how we can get current date and time using these classes and how they are different from each other.

Using Instant 

Instant represents a moment. For example, if World cup is starting at certain moment, it is exact that moment for everyone living in any part of world. If world cup is in Australia, then people in India can say that ,world cup started at different time than what what was time in Australia but it started at exact same moment on timeline for people of Australia as well as India. 

Using Instant, we can get the exact moment on timeline which is independent from time zones.

which in other words means that if two Instant objects are created at the same moment in any part of world, they will have exactly same value.

Instant represents date time in UTC(coordinated universal time), so it does not consider specific Zone and it is number of nanoseconds elapsed since epoch or since 1970-01-01T00:00:00Z. It is similar to GMT(Greenwich mean time).

All date times for specific Zones are calculated relative to UTC. 

For example : 
- A time in UTC (zone) itself, UTC + 0 is indicated by a Z( Z from Zulu time)
- Countries like Ireland, Portugal, Ghana follows UTC time zone, which means UTC + 0
- Japan follows UTC+9
- Barbados follows UTC-4

For complete list for all countries, you can check List of Countries with UTC time offsets

For our back end calculations in Java, we use Instant. For example, If we are running a job and want to calculate the time for next run we would use Instant. 


Now coming back to current date time using Instant, we need to use now() method as below :
Instant instant = Instant.now();
System.out.println("Current Date Time using Instant:" + instant);
Output:
Current Date Time using Instant:2021-01-09T22:25:06.385917300Z

Using ZonedDateTime

If you want to know date time, in your time zone, at a particular moment( represented by Instant) you can use ZonedDateTime.

You can either adjust the instant created above to get the ZonedDateTime like below :

Adjusting Instant object :

System.out.println("Using instant.atZone():" + instant.atZone(ZoneId.of("Europe/Amsterdam")));
Output:
Using instant.atZone():2021-01-09T23:25:06.385917300+01:00[Europe/Amsterdam]
This gives me exact date time in Amsterdam.

Using now(ZoneId zoneId) :

Alternatively you can use factory method now(ZoneId zoneId) defined in ZonedDateTime class itself like below:
System.out.println("Using ZonedDateTime.now(zoneId):" + ZonedDateTime.now(ZoneId.of("Europe/Amsterdam")));
Output:                                                                       Using ZonedDateTime.now(zoneId):2021-01-09T23:25:06.408922700+01:00[Europe/Amsterdam]

Using now() :

And there is one more option where in you can use factory method now() of ZonedDateTime class. However you must know that now() uses the default time zone of your JVM, which is subject to change, so better always pass zoneId.
System.out.println("ZonedDateTime with now():" + ZonedDateTime.now());
Output:                                                                       Using ZonedDateTime.now():2021-01-09T23:25:06.414919900+01:00[Europe/Berlin]
Another variant of now() is like below for using default time zone using ZoneId.systemDefault() as ZoneId.
System.out.println("Using ZonedDateTime.now(ZoneId.systemDefault())" + ZonedDateTime.now(ZoneId.systemDefault()));
Output:                                                                       Using ZonedDateTime.now(ZoneId.systemDefault()):2021-01-09T23:25:06.414919900+01:00[Europe/Berlin]

ZonedDateTime supports Day Light Savings

ZonedDateTime uses ZoneRules to determine how an offset varies for a particular time zone in case of Day light saving.

Lets take an example. Day light saving in Netherlands in 2021 is going to start from March 28, 2:00 AM and will end on October 31, 3:00 AM

Let us first try to see date time before(by 1 hour) Day light saving starts, i.e. at 1 AM
System.out.println("ZonedDateTime.of() before DLS: " + ZonedDateTime.of(2021, 3, 28, 1, 0, 0,0, ZoneId.of("Europe/Amsterdam")));
Output:
ZonedDateTime.of() before DLS: 2021-03-28T01:00+01:00[Europe/Amsterdam]

As you can see, it returned the time which we have asked for i.e. 1 AM and offset is of +1:00

Now let us try to see date time at the time when Day light saving is going to start i.e. at 2 AM.
System.out.println("ZonedDateTime.of() DLS start: " + ZonedDateTime.of(2021, 3, 28, 2, 0, 0,0, ZoneId.of("Europe/Amsterdam")));
Output                                                               ZonedDateTime.of() DLS start: 2021-03-28T03:00+02:00[Europe/Amsterdam]

As you can see , ZonedDateTime API automatically adjusted the time and returned time which is 1 hour ahead i.e. 3 AM instead of 2 AM and also now Offset is set to +2:00.

Using OffsetDateTime

OffsetDateTime represents a moment in date time which is some duration ahead(+) or behind(-) the UTC or in other words with offset from UTC without a Time ZoneId such as "Europe/Amsterdam".

You can use ZoneOffset class to represent offset in hours, hours: minutes or hours: minutes: seconds.

So if the OffSet is zero, then OffsetDatTime represents Instant, which is in UTC.
System.out.println("Using OffsetDateTime.now():" + OffsetDateTime.now());
Output:                                                                       Using OffsetDateTime.now():2021-01-09T23:25:06.415920100+01:00

Using LocalDateTime

LocalDateTime gives you date time without any offset(from UTC) information or any Zone information, which in other words means it can not represent moment on the timeline.
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("localDateTime is:" + localDateTime);
Output:
localDateTime is:2021-01-09T23:25:06.416918700

Summary

- There are multiple way you can get hold of current date time using Java 8 API depending upon your requirements.
- Instant gives you moment on timeline and gives you date time in UTC and does not consider time zone.
- Any two instances of Instant created at same moment in any part of world will give you same objects, which means they represents the same moment on the timeline.
- You can use ZonedDateTime class for date time with Offset from UTC and Zone information.
- You can use OffsetDateTime to get date time with OffSet from UTC.
- You can use LocalDateTime ,if you want to get date time as shown on your clock.

Static Nested Classes Java

In Java, it is possible to define a class within another class. Class defined within another Class is called a Nested Class.


Nested class is treated as a member of the Outer class because it is also defined within the Outer class like its other members(variables or methods).

public class OuterClass {
    class NestedClass {

    }
}

Although Outer class can be declared only either as public or package private(no access modifier) but Nested classes can have any of the access modifier public, private, protected or package private(no access modifier), reason being , nested class is also just like a member of the Outer class, so just like you can have public, private ,protected or package private instance variables or methods, you can have these access modifiers for nested classes as well.

Now if you define your nested class as static, then they are called static nested class and if you don't define them as static then they are called non static nested classes or Inner classes. So Nested classes are broadly of two types :

- Static Nested Classes

- Inner Classes   

In this post, we will discuss static nested classes.

Static Nested Class :

They are just like any other Java class which are defined with a static modifier within a Outer class for the packaging convenience and from packaging convenience I mean that instead of creating another top level class we packaged this nested class within another class as this nested class made sense only in the context of enclosing Outer class. We will see example later.
public class OuterClass {
    public static class NestedClass {

    }
}

Rules for static nested class as a static member of Outer class

Rules for instantiating static nested class

Because static nested classes are static ,so just like the static methods and variables they follow the rules which static members within a class follows. So just like static methods and variables, they belong to their Outer class and not to the instance(s) of the Outer class. So you don't need to instantiate OuterClass first but you just use <outer class><dot><nested class> syntax to instantiate the nested classes as in below example.
public class TestClass {
    public static void main(String[] args) {
        OuterClass.NestedClass nestedClass = new OuterClass.NestedClass();
    }
}

Rules for accessing the Outer class members from static nested class

Static nested class being static, can only access the static members of its outer class. It does not have access to the instance members of the Outer class. This makes sense again, if you think just from static perspective. Any static method of our class in general can only access the static variables or static methods only, so the same concept is applied for static nested classes as well, because they are also the static members of the Outer class from Outer class perspective.
public class OuterClass {
    private static String x;
    private String y;

    public static class NestedClass {
        public void test() {
            // x is accessible
            System.out.println(x);

            // y is not accessible here and it will give compiler time error 
            // "No static field 'y' can not be referenced from static context.
            System.out.println(y);
        }
    }
}
You might have noticed that test() method itself is not static but still the compiler warning says "can not be referenced from static context", this is because although test() method is not a static method but still the class in which it has been defined as , is static, so from OuterClass perspective "y" which is not a static member of OuterClass is being referred from within it's static member NestedClass.

Other than that from its own existence perspective, they are just like any normal Java classes, which means :

- You can create their objects(By using <OuterClass><dot><NestedClass> syntax).
- You can have instance variables within them.
- You can have instance methods within them.
- You can have static methods in them.
- You can extend them.
- You can declare them final.

Only difference from top level java class is that it can be declared static and it can have any of the access modifier which means public, package private, protected or private.

So to conclude this section, you need to see static nested classes from two perspective :

- As a static member of the Outer class and rules for accessing it(nested class) being a static member     And rules for accessing Outer class members.
- As a normal Java class which is just packaged within another class.

What is the use of Static nested Classes ?

1. Packaging Convenience and as Helper classes

In general, we use nested class when the class is not required to be used anywhere else other than in the class it is part of. For example we can define helper classes using nested static classes. And if they need to be accessed also from within Outer class only, we can declare static nested class as private, so that it is invisible to the outside world.

For example: 

1. If we see java.util.Collections class in JDK, you can find lots of private nested classes like:

SetFromMap
ReverseComparator
CopiesList

As these classes serve only to Collections class, are not being used from anywhere else in JDK and does not use any instance variable or method of the outer Collection class, they have been kept as private and nested static classes.

2. Static nested classes specially should be used(instead of inner classes) when you don't want to use enclosing class's instance members in nested class but want to keep Outer class and Nested class together for packaging convenience. For example, in the Builder Pattern that we discussed in one of previous post, Builder is created as static nested class. This builder does not use/call any of the Outer class instance variable/method but as we know that this builder makes sense only in context of Student class, so we packaged Student and its builder together.

And we can instantiate this static nested builder without using the instance of the Outer class as below:
Student.StudentBuilder studentBuilder2 = new Student.StudentBuilder("2",                                                                                                     "Sachin", "Tendulkar").withAge("47");
3. They are very useful for creating Request and Response type of classes for your restful services as you can easily map them to the Json structure.
public class Employee {
    private String name;
    private String age;

    public static class Address {
        private int houseNumber;
        private String streetName;
    }
}

2. Better Readability and Maintainability 

It leads to more readable and maintainable code because you keep closely used classes together at one place instead of spreading it across in multiple top level classes.

Summary

- Nest a class inside another class as a static nested class, when the class you are going to write is going to be used only within that class or in its context.
 - Make it static because you don't need access to the instance members of Outer class. If you need access then go for Inner classes.
- Only nested classes can be declared as static. Top level classes can not be declared as static.
- Static nested classes can be declared public, protected, package private or private. Top level classes can only be public or package private.
- If a static nested class is declared as public, but Outer class is package private, then you can access nested class also within that package only because static nested class can only be accessed by using class name of the Outer class and if Outer class is not visible then static nested class will not be visible even if it is public.
- Nested static classes are like static members of the Outer class and follows the rules of static within Outer class.
- Use them as helper classes for better readability or for request response for rest service.

Thank you for reading. If you any question or suggestion to add further in this post, you can let me know in comments section.

Builder Design Pattern

Hello Friends,

In this tutorial, we will discuss Builder design pattern. 


Key topics we are going to discuss are :

- Which category Builder Design Pattern falls in ?
- What problem builder Pattern is solving or when to use Builder pattern?
- Builder Pattern 
- Builder Pattern Example
- Advantages of Builder Pattern
- Disadvantages of Builder Pattern

Which category Builder Design Pattern falls in ?


Builder pattern falls under Creational design patterns category, as it deals with the creation of object(s).Please note that Builder design pattern that I am going to describe here is not GOF design pattern but the one suggested by Joshua block in Effective Java, as I personally see this pattern used for more often or more practical than the one suggested by GOF.

What problem builder Pattern is solving or when to use Builder pattern?


In nutshell, you should use Builder design pattern when :
- You have a class , which has some mandatory fields and a some optional fields, which in other words means that your object can be constructed in various ways as per requirements. Although you are free to use it with a class with all mandatory fields as well when number of fields are too many(usually more than four is good candidate).
- You want objects of your class to be immutable, which means once objects are instantiated there state can not be changed after that.

Now lets discuss these points in more detail.

You have a class with some mandatory and some optional fields :

What is the problem with having optional fields.

Let us say you have below Student class with mandatory and optional fields and have a constructor with all the fields.
package com.blogspot.javasolutionsguide;

public class Student {
    //mandatory fields
    private final String id;
    private String firstName;
    private String lastName;                                                                                                                                            //optional fields
    private String age;
    private String houseNumber;
    private String streetNumber;

    public Student(String id, String firstName, String lastName, String age, String houseNumber, String streetNumber) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
        this.houseNumber = houseNumber;
        this.streetNumber = streetNumber;
    }

    public String getId() {
        return id;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public String getAge() {
        return age;
    }

    public String getHouseNumber() {
        return houseNumber;
    }

    public String getStreetNumber() {
        return streetNumber;
    }
}

Now, say the client of this code might want to create instance of Student with 

- Only Mandatory fields
- All the Mandatory as well as optional fields
- Mandatory fields and one or more of the optional fields

Then the constructors for above scenarios will look like as below :
//Only Mandatory fields                                                       Student student2 = new Student("201", "firstName2", "surName2", null, null, null);
//All the Mandatory as well as optional fields                               Student student1 = new Student("101", "firstName1", "surName1", "16", "11", "2");
//Mandatory fields and one or more optional fields                           Student student3 = new Student("301", "firstName3", "surName3", "20", null, null);
Student student4 = new Student("301", "firstName4", "surName4", "20", "22", null);
Now what is the problem with above constructors?

Actually there are multiple problems, like 
- Client code has to unnecessarily pass null for all optional fields.
- Code readability is not good. As the number of parameters grow, it becomes difficult and error prone for client code to understand what needs to be passed at which position and later to read for the person who is going to maintain the code.
- When adjacent parameters are of same data type, you might accidently exchange their values which will go unnoticed at compile time but create some severe bug at run time. For example, developer can accidently interchange values for age and houseNumber.

So What can you do to solve these problems ?

Probably we can have look at the Telescoping constructor pattern.

In Telescoping constructor pattern, we create multiple constructor overloads starting with one with all mandatory fields and then with one optional field and then with two optional fields and so on until we have constructor with all fields.

Each constructor calls another constructor with one more optional field and passes the default value for the optional field(can be null or any other default you want to set) until the last constructor with all optional fields is called.
package com.blogspot.javasolutionsguide;

public class Student {

    //Mandatory fields
    private String id;
    private String firstName;
    private String lastName;

    //Optional fields
    private String age;
    private String houseNumber;
    private String streetNumber;

    public Student(String id, String firstName, String lastName) {
        this(id, firstName, lastName, "0");
    }

    public Student(String id, String firstName, String lastName, String age) {
        this(id, firstName, lastName, age, "0");
    }

    public Student(String id, String firstName, String lastName, String age, String houseNumber) {
        this(id, firstName, lastName, age, houseNumber, "0");
    }

    public Student(String id, String firstName, String lastName, String age, String houseNumber, String streetNumber) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
        this.houseNumber = houseNumber;
        this.streetNumber = streetNumber;
    }
}

Now let us see which problems telescoping constructor solved :

- Client code no longer has to pass null for all the optional fields as well.
- From client code perspective, readability is better.

But telescoping constructors comes with its own problems:

- What if more optional fields are added in Student class in future, then for each new field another constructor needs to be introduced.
- Still you need to carefully see all overloads of the constructor and choose the one which suits your requirement.
- Still if you have say age and streetNumber but houseNumber is not available, then you need to instantiate Student class like below, so still client need to pass in null value for optional field.
Student student = new Student("101", "firstName", "lastName", "35", null, "3");

- And still there is possibility of getting exchange of values of same data type, when the number of optional fields are too many.

We will see how builder pattern solves these problems later but for now let us discuss the other aspect which makes a case for using builder pattern.

You want objects of your class to be immutable :

If you don't want state of your object to get changed once it has been created(and of course it has lots of fields), you can use build pattern, as builder pattern makes sure your object is immutable once it is created.

Advantages of Immutable classes :
- They are more reliable as it is known that their state is not going to change after creation. 
- They are inherently thread safe and don't need any synchronization.
- They make great candidates to be used as a key of a HashMap or to be put in a HashSet.

Now let us see implementation of Builder pattern by taking example of our Student class. 

Builder pattern


- In builder pattern , you leave the responsibility of creating object or instantiating your class to Builder which is another class which has exactly same number of fields as your class whose objects builder is going to build.

- As your builder class is going to be used only for creating objects of your class and is not going to be used elsewhere, it is defined as static nested class within your class.

- You provide a builder's constructor with only mandatory fields and then you provide methods(mutators) in builder to set the remaining optional fields. You can chain these methods as each of these method again returns Builder. Note that till now we are talking only about using builder constructor and using methods to set other optional fields and all these are still part of Builder object and we have not yet created actual Student object, so we are not concerned about immutability yet.

So in terms of code, we are here :
Student.StudentBuilder studentBuilder2 = new Student.StudentBuilder("2",                                                           "Sachin", "Tendulkar").withAge("47");
- Now all we need to do is call build() method of our builder on the created builder instance like below :
studentBuilder2.build()
which in turn calls private constructor of the Student class and passes "this" reference which is reference to the builder which is calling build() method. 
public Student build() {
     return new Student(this);
}
In the constructor, values are copied from builder to the Student instance variables and a complete immutable student object is created.
private Student(StudentBuilder studentBuilder) {                                            
    id = studentBuilder.id;                                                            
    firstName = studentBuilder.firstName                                            
    lastName = studentBuilder.lastName;                                                
    age = studentBuilder.age;                                                        
    houseNumber = studentBuilder.houseNumber;                                        
    streetNumber = studentBuilder.streetNumber;                                
}

Builder pattern example

package com.test.builder;

public class Student {
    //Mandatory fields
    private final String id;
    private final String firstName;
    private final String lastName;

    //Optional fields
    private final String age;
    private final String houseNumber;
    private final String streetNumber;

    private Student(StudentBuilder studentBuilder) {
        id = studentBuilder.id;
        firstName = studentBuilder.firstName;
        lastName = studentBuilder.lastName;
        age = studentBuilder.age;
        houseNumber = studentBuilder.houseNumber;
        streetNumber = studentBuilder.streetNumber;
    }

    public String getId() {
        return id;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public String getAge() {
        return age;
    }

    public String getHouseNumber() {
        return houseNumber;
    }

    public String getStreetNumber() {
        return streetNumber;
    }

    public static class StudentBuilder {
        //Mandatory fields
        private final String id;
        private final String firstName;
        private final String lastName;

        //Optional fields
        private String age;
        private String houseNumber;
        private String streetNumber;

        public StudentBuilder(String id, String firstName, String lastName) {
            this.id = id;
            this.firstName = firstName;
            this.lastName = lastName;
        }

        public StudentBuilder withAge(String age) {
            this.age = age;
            return this;
        }

        public StudentBuilder withHouseNumber(String houseNumber) {
            this.houseNumber = houseNumber;
            return this;
        }

        public StudentBuilder withStreetNumber(String streetNumber) {
            this.streetNumber = streetNumber;
            return this;
        }

        public Student build() {
            return new Student(this);
        }
     }

    @Override
    public String toString() {
        return "Student{" +
                "id='" + id + '\'' +
                ", firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", age='" + age + '\'' +
                ", houseNumber='" + houseNumber + '\'' +
                ", streetNumber='" + streetNumber + '\'' +
                '}';
    }
}

and here is the test class :
package com.blogspot.javasolutionsguide;

public class TestStudentBuilder {
    public static void main(String[] args) {
        Student.StudentBuilder studentBuilder1 = new Student.StudentBuilder("1",                                              "Gauarv", "Bhardwaj");
        System.out.println(studentBuilder1.build());

        Student.StudentBuilder studentBuilder2 = new Student.StudentBuilder("2",                                             "Sachin", "Tendulkar").withAge("47");
        System.out.println(studentBuilder2.build());
    }
}

and here is the output:
Student{id='1', firstName='Gauarv', lastName='Bhardwaj', age='null', houseNumber='null', streetNumber='null'}
Student{id='1', firstName='Sachin', lastName='Tendulkar', age='47', houseNumber='null', streetNumber='null'}

Advantages of Builder Pattern :


- Client code is much more clean and readable. If we want to create object only with the mandatory fields ,we can just create builder instance with mandatory fields and then call build() method which will return us the Student object with only mandatory fields, however if we want to create Student object with some optional fields we can call respective methods like withAge() or withHouseNumber() and get Student object with all these fields as well. So we are not forcing client code to pass unnecessarily null values for the optional fields.
- Problem with getting values exchanged is also resolved as optional fields can be added by calling their respective methods which have clearly defined names.
- Object created using Builder pattern is immutable, as there are no setters in the Student class and also the constructor is private, so the only way to create Student object is via builder.

Disadvantages of Builder Pattern :


- Disadvantage is that you have to write lot of extra code for Builder class and as and when you need to add more fields, you need to add those fields both to your Student class as well as to your builder class. This is one of the reason that you should keep your Builder class within your class to be built as static nested class so that you don't miss to add new field to builder as well .

Overall better code readability and immutability that Builder patter offers overweighs disadvantages it has, in my opinion.

Thank you for reading. Let me know, if you have any questions in comments section.

How to convert Array to List in Java

Hello Friends,

In this tutorial, we will learn, various ways in which we can convert an array to a List. 

How to install Apache Web Server on EC2 Instance using User data script

Hello Friends,

In this tutorial, we will see how we can install Apache Web Server on EC2 instance using user data script.


How to Install Maria DB, create Database and Execute Queries

Hello Friends,

In this tutorial,we will see :

1. How to Install Maria DB
2. How to connect to Maria DB,Create Database and Execute Queries

What is @Qualifier annotation in Spring and why it is used


In this tutorial, we will explore the @Qualifier annotation of Spring framework.

1. What does @Qualifier annotation do
2. @Qualifier examples


AWS Lambda to save data in DynamoDB

In this tutorial, we will see how using AWS Lambda we can save data in Dynamo DB.

Here are the steps which are required :

1. Create a table in the Dynamo DB with the name Employee
2. Create a AWS Lambda function which can save firstName and surName of an employee using a Employee POJO in the Dynamo DB
3. Create a Policy which will give Read/Write access to only Employee table of DynamoDB
4. Attach Policy to a Role
5. Upload the code of AWS lambda function in the form of jar in the AWS lambda console
6. Attach role created in step 4 to the AWS Lambda
7. Run Test event to invoke AWS Lambda to save Employee data in Dynamo DB

AWS Lambda function with Java Pojo as Input Output Example

In the previous tutorial, we saw How to Create AWS Lambda function with Java and we passed String as input and also returned String as Output.I will recommend to go through that tutorial first, if you are creating lambda function for the first time.

In this tutorial, we will see, how we can pass Java Plain old Java object(POJO) as input and also return it as Output.



Here we will be implementing RequestHandler interface.
package com.blogspot.javasolutionsguide;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.blogspot.javasolutionsguide.input.Input;
import com.blogspot.javasolutionsguide.output.Output;

public class HelloWorldWithPojoInputOutput implements RequestHandler<Input, Output> {

    @Override
    public Output handleRequest(Input input, Context context) {
        String message = String.format("Hello %s%s.", input.getName(), " " + "from" + context.getFunctionName());
        return new Output(message);
    }
}

And here is our Input and Output classes.
package com.blogspot.javasolutionsguide.input;

public class Input {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

package com.blogspot.javasolutionsguide.output;

public class Output {
    private String message;

    public Output(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

For uploading the code to AWS console, please follow steps from my previous tutorial.

Once you have uploaded your jar in AWS lambda console, click on "Select a Test event" and then "configure test events".

Enter event name as "HelloWorldWithPojoInputOutput" and replace following:
{
  "key1": "value1",
  "key2": "value2",
  "key3": "value3"
}

with following :
{
  "name" : "Gaurav Bhardwaj"
}

Click on Create button. Now click on Test button and you should see your lambda fucntion executed successfully with message "Hello Gaurav Bhardwaj", which is the output returned by our lambda function.

You can find all code of this tutorial in GitHub

Summary

So in this tutorial, we saw how we can pass POJO to lambda function and also we can return POJO from a lambda function.


How to create AWS Lambda function with Java


In this tutorial, we will see how we can create AWS Lambda function in Java and I tell you, it is quite easy to do so.

Basically, there are three ways in which we can create AWS Lambda function :

- By implementing RequestHandler interface
- By implementing RequestStreamHandler interface
- Custom implementation, which does not require us to implement any AWS specific interface


AWS Lambda function by implementing RequestHandler interface

For using this method of creating AWS lambda function, we need to have following dependency in our project :
<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-lambda-java-core</artifactId>
    <version>1.1.0</version>
</dependency>

And below is how your class will look like:
package com.blogspot.javasolutionsguide;

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

public class HelloWorldWithRequestHandler implements RequestHandler<Object, Object> {

    @Override
    public Object handleRequest(Object input, Context context) {
        return String.format("Hello %s%s.", input, " from " + context.getFunctionName());
    }
} 

Once you have created a maven project with above dependency and class in your project, maven build the project , which will create jar for you in the target folder of your project.

Now open the AWS console, got to Services and search for AWS Lambda.


On the following screen ,click on Create Function.



On following screen, enter Function name "HelloWorld" and choose Runtime as Java 11.


In Permissions section, choose "Create a new role with basic Lambda permissions"and AWS Lambda will create and execution role with name HelloWorld-role-jc6cmpnj. This role is required to allow AWS Lambda to upload logs to AWS Cloudwatch logs.

Click on Create Function.


You will see following screen, where it says that "Successfully created the function HelloWorld. You can now change its code and configuration. To invoke your function with a test event, choose Test.




Now in the Function code section, click on the upload button and browse on your computer for the jar that you created earlier.

- Also, in the Handler textbox, replace example with package name where your "HelloWorldWithRequestHandler" class is residing, which in our case it is "com.blogspot.javasolutionsguide"
- And replace Hello with "HelloWorldWithRequestHandler".
- And replace handleRequest will stays as is ,because we also have same method name in our class.
Click on Save button on extreme right side of the screen.



Now to test our lambda function, we need to configure test event(s),for which we will click on "Select a Test event" drop down and then click on "Configure test events".


You will see following screen.Enter Event name as "HelloWorldEvents" and replace following
{
  "key1": "value1",
  "key2": "value2",
  "key3": "value3"
}
with just your name like as below :
"Gaurav Bhardwaj"

and click on Create button.


Now click on Test button and you should see your lambda function executed successfully with message "Hello Gaurav Bhardwaj from HelloWorld", which is the output returned by our lambda function.


If you click on the logs link in the above screen, it will take you to the AWS Cloudwatch screen where you can see that for your lambda function a LogGroup has been created and under which you have LogStream where you can see logs of your lambda function.This was the reason we assigned role to our lambda function, because AWS lambda used that role to push logs to the Cloudwatch.


AWS Lambda function by implementing RequestStreamHandler interface 

In this case you need to follow exact same steps as in above case.It is just that in the code you need to implement RequestStreamHandler interface rather than RequestHandler interface as below.
package com.blogspot.javasolutionsguide;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

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

public class HelloWorldWithRequestStreamHandler implements RequestStreamHandler {

    @Override
    public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
        int letter;
        while ((letter = inputStream.read()) != -1) {
            outputStream.write(Character.toUpperCase(letter));
        }
    }
}

AWS Lambda function by custom implementation, which does not require us to implement any AWS specific interface

You can also have your custom lambda function ,which does not follow signature from some AWS specific interface. You can even omit Context object as well, if you don't want it.

In the following code, I have tried to put two handler methods, one with Context object and one without Context object. To test these both ,you just need to change the name of the method in the AWS console and it will start hitting that method.

Also ,we can see that from Context object ,we can get lots of useful information like name of AWS function, its version, ARN, how much memory is allocated to the function(by default it is 512 MB). 
package com.blogspot.javasolutionsguide;

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

public class HelloWorld {
    //Handler method without Context
    public String sayHelloWorldWithoutContext(String name) {
        return String.format("Hello %s.", name);
    }

    //We need to add aws-lambda-java-core dependency if we add Context as parameter.
    public String sayHelloWorldWithContext(String name, Context context) {
        context.getLogger().log("Lambda Function Name:" + context.getFunctionName() +
                "Version:" + context.getFunctionVersion() +
                "Arn:" + context.getInvokedFunctionArn() +
                "Allocated Memory:" + context.getMemoryLimitInMB() +
                "Remaining Time:" + context.getRemainingTimeInMillis());
        return String.format("Hello %s.", name);
    }
}
Also in the following example, we can see that if we have two handler methods with same name in our class, the handler method which has Context object as its parameter will be called.

package com.blogspot.javasolutionsguide;

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

public class HelloWorldWithMultipleHandlersWithSameName {
    public String handler(String name) {
        return String.format("Hello %s.", name);
    }

    public String handler(String name, Context context) {
        return String.format("Hello %s%s.", name, " Memory Allocated:" + context.getMemoryLimitInMB());
    }
}
You can find all code of this tutorial in GitHub

Summary :

- So, we saw how can create AWS lambda function in various ways in Java.
- Name of the handler method does not matter.You can choose any name of your choice.
- If you have two handler methods with same name in your class, the handler method which has Context object as its last parameter will be called.
- The first parameter of the handler method is the input to the handler, which can be 
   - Event data published by an event source like S3 in the form of predefined AWS event types like S3Event.
   - Custom input (Primitive or Object type).
- In order for AWS lambda to successfully invoke the handler method, the function must be invoked     with input data that can be serialized into the data type of the input parameter.
- If you are invoking your lambda function synchronously(Invoke type RequestResponse), then you can return any allowed primitive or Object type from your handler, however if you are invoking your lambda function asynchronously(Invoke type Event), then return type of your handler must be void.