Introduction to Java Stream API

Introduction to Java Stream API

Java Stream API is there since Java 8. It is used to express computation on data is a short and elegant way. In the following post I will introduce you to the most common methods to give you an idea what you can achieve with the Java Stream API.

Java Stream API is there since Java 8. It is used to express computation on data is a short and elegant way. In the following post I will introduce you to the most common methods to give you an idea what you can achieve with the Java Stream API.

Streams vs Collections

Before jumping right into the code I want to explain the difference between Streams and Collections. It is clear that both have properties in common, they can both be iterated for example. You can iterate through Collection external with e.g. for each loops. Instead you don't loop explicit through streams. You express your computations in a functional way and the Stream API deals for iterations internally. Also the Stream API is lazy, its elements are computed or fetched via network by demand. Collections are a in memory data store which means that every element in your Collection has to be computed and stored in your RAM before you can access it. But this does not mean that you can't use streams for already computed data. It rather makes Streams more flexible than Collections in specific situations. You also can create Streams out of Collection based data structures as I will do in the following examples.

Examples

In the following I will show you some examples of the usage of Streams and I will also compare my solution to the classical programming approach.

filter

If you want to filter a list, you can just use filter.

Let's assume we have a list of words.

List<String> words = Arrays.asList("Abra", "Kadrabra", "Aloha");

Now we want to filter all words which starts with a capital A and print them.

words.stream()
        .filter(word -> word.startsWith("A"))
        .forEach(System.out::println);

We actually use two stream methods here. First we transform the list to a stream and filter and words which starts with a capital A. On the resulting stream we are printing out every word with System.out.println.

You probably have seen similar lambda expressions like the on in the filter before, but maye you have not seen many which I used in the forEach method. System.out::println is just syntactic sugar for following lambda expression: x -> System.out.println(x).

We can also write the code by not using streams by simply using a for loop:

for (String word : words) {
        if (word.startsWith("A")) {
            System.out.println(word);
    }
}

This solution is in my opinion less elegant and can be written more expressive as I showed in the upper code snippet.

We can even improve our Stream example by creating a method for the startsWith condition in a external method.

words.stream()
        .filter(StreamExamples::startsWithA)
        .forEach(System.out::println);

with

private static boolean startsWithA(String word) {
    return word.startsWith("A");
}

sum

With the Stream API you also never have to write code like this again

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

int sum = 0;
for (Integer number : numbers) {
    sum += number;
}
System.out.println(sum);

Instead you can write

System.out.println(numbers.stream().mapToInt(Integer::intValue).sum());

which does exactly the same as the upper code snippet.

map

map projects every element of a stream into another form. As I used mapToInt to project the element to Int's, I can use map to project every element of a stream in to a new element.

numbers.stream()
        .map(number -> number * number)
        .forEach(System.out::println);

A traditional approach of writing this code would be following snippet:

for (Integer number : numbers) {
    int squaredNumber = number * number;
    System.out.println(squaredNumber);
}

flatMap

Next lets assume we have following data source:

List<List<Integer>> matrix = Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4), Arrays.asList(5, 6));

Our task is it now to sum up all element in the matrix.

To flat the data structure we can use flatMap. It concatenates streams and generates a single stream as a result. So to compute the sum, we can use first flatMap to concatenate multiple streams into one and then use mapToIntand sum as shown in the upper example of sum.

System.out.println(matrix.stream().flatMap(Collection::stream).mapToInt(Integer::intValue).sum());

flatMap allows use to abstain from for-loops in for-loops and write elegant code in one line.

Your colleagues will thank you if they pull your code.

collect

Last but not least you can transform a stream into a traditional data structure by using collect.

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

List<Integer> evenNumbers = numbers.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());

Conclusion

I have uploaded all examples to my Github

Java 8 introduced Java Streams which allows us to express data processing queries in a short functional and elegant way. There are many more operations to explore, this post should just gave you an introduction to the Stream API. I hope you are motivated now to use the Stream API next time when you are using Java.

How to Build a CRUD API with Java, MongoDB, and Spring Boot

How to Build a CRUD API with Java, MongoDB, and Spring Boot

This tutorial shows how to build a CRUD API with Java, MongoDB, and Spring Boot. How to build a CRUD API with Java and MongoDB. In this tutorial, you create a Java data model class and mapped it to a MongoDB domain document using Spring Data annotations. You use a simple embedded MongoDB database as the datastore. You use Spring Boot to quickly and easily expose your data model via a REST API. Finally, you secured the REST API using Okta and Okta’s Spring Boot Starter.

This tutorial leverages two technologies that are commonly used to build web services: MongoDB and Java (we’ll actually use Spring Boot). MongoDB is a NoSQL database, which is a generic term for any non-relational databases and differentiates them from relational databases. Relational databases, such as SQL, MySQL, Postgres, etc…, store data in large tables with well-defined structures. These structures are strong and tight and not easily changed or customized on a per-record basis (this structure can also be a strength, depending on the use case, but we won’t get too deep into that here). Further, because relational databases grew up pre-internet, they were designed to run on monolithic servers. This makes them hard to scale and sync across multiple machines.

NoSQL databases like MongoDB were developed, to a large degree, to fit the needs of internet scaling where server loads can balloon dramatically and the preferred growth pattern is the replication of servers, not scaling a single monolithic server. MongoDB is a document-based database that natively stores JSON and was built for distributed scaling. Mongo documents are JSON objects and have no predetermined structure on the side of the database. The structure of the documents is determined by the application and can be changed dynamically, adding or removing fields as needed. This means that Mongo documents are very flexible (possibly a blessing and a curse, FYI). Also, because MongoDB produces JSON documents, it has become very popular with many of the JS-based front-ends where Javascript is king and JSON is easily handled.

Spring Boot is an easy to use web application framework from Spring that can be used to create enterprise web services and web applications. They’ve done an admirable job simplifying the underlying complexity of the Spring framework, while still exposing all of its power. And no XML required! Spring Boot can be deployed in a traditional WAR format or can be run stand-alone using embedded Tomcat (the default), Jetty, or Undertow. With Spring you get the benefit of literally decades of proven enterprise Java expertise - Spring has run thousands of productions applications - combined with the simplicity of a modern, “just work” web framework, incredible depth of features, and great community support.

In this tutorial, you will create a simple Java class file to model your data, you will store this data in a MongoDB database, and you will expose the data with a REST API. To do this, you will use Spring Boot and Spring Data.

Once you have created an unsecured REST API, you are going to use Okta and Spring Security (along with Okta’s Spring Boot Starter) to quickly and easily at JSON Web Token (JWT) authentication to your web service.

Install Java, Spring Boot, MongoDB, and Other Project Dependencies

You’ll need to install a few things before you get started.

Java 11: This project uses Java 11. If you don’t have Java 11, you can install OpenJDK. Instructions are found on the OpenJDK website. OpenJDK can also be installed using Homebrew. SDKMAN is another great option for installing and managing Java versions.

HTTPie: This is a simple command-line utility for making HTTP requests. You’ll use this to test the REST application. Check out the installation instructions on their website.

Okta Developer Account: You’ll be using Okta as an OAuth/OIDC provider to add JWT authentication and authorization to the application. Go to developer.okta.com/signup and sign up for a free developer account, if you haven’t already.

Download a Skeleton Project From Spring Initializr

To create a skeleton project, you can use Spring Initializr. It’s a great way to quickly configure a starter for a Spring Boot project.

Open this link to view and download your pre-configured starter project on Spring Initializr.

Take a look at the settings if you like. You can even preview the project by clicking the Explore button at the bottom of the page.

Once you’re ready, click the green Generate button at the bottom of the page to download the starter project to your computer.

The starter for this project is a Spring Boot 2.2.2 project that uses Java as the application language and Gradle as the build system (there are other options for both). We’ve covered Gradle in-depth in a few other posts (see below), so we won’t go into too much detail here, except to say that you won’t need to install anything for Gradle to work because of the Gradle wrapper, which includes a version of Gradle with the project.

The included dependencies in this project are:

  • Spring Web (spring-boot-starter-web): web application functionality
  • Spring Data MongoDB (spring-boot-starter-data-mongodb): MongoDB functionality
  • Embedded MongoDB Database (de.flapdoodle.embed.mongo): embed an in-memory MongoDB database, great for testing and tutorials like this
  • Rest Repositories (spring-boot-starter-data-rest): needed for the @RepositoryRestResource annotation, which allows us to quickly generate a REST api from our domain classes
  • Okta (okta-spring-boot-starter): starter that simplifies integrating OAuth 2.0 and OIDC authentication and authorization
  • Lombok (lombok): a getter, constructor, and setter helper generator via annotations

Before you do anything else, you need to make two changes to the build.gradle file.

  1. Temporarily comment out the dependency okta-spring-boot-starter
  2. Change de.flapdoodle.embed.mongo from testImplementation to implementation

You’re doing number one because you won’t be configuring the JWT OAuth until later in the tutorial, and the application won’t run with this dependency in it unless it is configured. You’re changing the de.flapdoodle.embed.mongo dependency because typically this embedded database is only used in testing, but for the purposes of this tutorial, you’re using it in the actual implementation. In a production situation, you’d use a real MongoDB instance.

The dependencies {} block should look like this:

dependencies {  
    implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'  
    implementation 'org.springframework.boot:spring-boot-starter-data-rest'  
    implementation 'org.springframework.boot:spring-boot-starter-web'  
    //implementation 'com.okta.spring:okta-spring-boot-starter:1.3.0'  
    compileOnly 'org.projectlombok:lombok'  
    annotationProcessor 'org.projectlombok:lombok'  
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
    implementation 'de.flapdoodle.embed:de.flapdoodle.embed.mongo'  
}

With that done, you can run the application using:

./gradlew bootRun

If all goes well, you’ll see a bunch of output that ends with something like:

...
2019-12-16 20:19:16.430  INFO 69710 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2019-12-16 20:19:16.447  INFO 69710 --- [           main] c.o.m.m.MongodboauthApplication          : Started MongodboauthApplication in 16.557 seconds (JVM running for 18.032)

Open a second shell and use HTTPie to make a request:

$ http :8080

HTTP/1.1 200
Content-Type: application/hal+json;charset=UTF-8
Date: Mon, 16 Dec 2019 03:21:21 GMT
Transfer-Encoding: chunked

{
    "_links": {
        "self": {
            "href": "http://localhost:8080/profile"
        }
    }
}

The astute out there might be wondering why this request returned a 200 instead of a 404 (since you haven’t actually defined a controller endpoint).

When you included the spring-boot-starter-data-rest dependency, it included the functionality to automatically generate a “hypermedia-based RESTful front end” (as Spring describes it in their docs).

Create a Hypermedia-based RESTful Front End

What is a “hypermedia-based RESTful front end”? It is a REST API that uses Hypertext Application Language (HAL) format to output descriptive JSON. From the HAL Specification GitHub page:

HAL is a simple format that gives a consistent and easy way to hyperlink between resources in your API. Adopting HAL will make your API explorable, and its documentation easily discoverable from within the API itself. In short, it will make your API easier to work with and therefore more attractive to client developers.

Thus it’s a systematic way for a REST API to describe itself to client applications and for the client applications to easily navigate between the various endpoints.

Currently, there’s not much going on with the application, so there isn’t much to see in the response. It’ll make more sense a little later as we add endpoints and data.

Create a Domain Class with Java

To get the ball rolling, you need to create a domain class. Your application is going to be a simple refrigerator inventory application. You’ll be able to add, update, delete, and list all the items in a refrigerator. Each item will have 4 properties: 1) a unique ID assigned by the database, 2) a name, 3) an owner, and 4) and expiration date.

Create a RefrigeratorItem Java class and copy and paste the code below into it.

src/main/java/com/okta/mongodb/mongodboauth/RefrigeratorItem.java

package com.okta.mongodb.mongodboauth;  

import lombok.AllArgsConstructor;  
import lombok.Data;  
import lombok.NoArgsConstructor;  
import org.springframework.data.annotation.Id;  
import org.springframework.data.mongodb.core.mapping.Document;  

import java.util.Date;  

@Document  
@Data  
@AllArgsConstructor  
@NoArgsConstructor  
public class RefrigeratorItem {  

    @Id  
    private String id;  
    private String name;
    private String owner;
    private Date expiration;
}

The @Document annotation is the Spring Data annotation that marks this class as defining a MongoDB document data model. The other annotations are Lombok helpers that save us from the drudgery of creating various getters, setters, and constructors. See more about Lombok at the project’s website.

NOTE: If you’re using an IDE for this tutorial, you may need to install and enable the Lombok plugin.

Create a Spring Data Repository

The next step is to define a Spring Data repository. This is where some pretty incredible auto-magicking happens. You’re going to create a base class that extends the Spring Data class MongoRepository. This superclass includes all the necessary code for reading and writing our domain class to and from the database. Further, you will use the @RepositoryRestResource annotation to tell Spring Boot to automatically generate a REST endpoint for the data using the HAL JSON spec. mentioned above.

Create the repository class shown below.

src/main/java/com/okta/mongodb/mongodboauth/RefrigeratorRepository.java

package com.okta.mongodb.mongodboauth;  

import org.springframework.data.mongodb.repository.MongoRepository;  
import org.springframework.data.rest.core.annotation.RepositoryRestResource;  

@RepositoryRestResource(collectionResourceRel = "fridge", path = "fridge")
public interface RefrigeratorRepository extends MongoRepository<RefrigeratorItem, String> {  
}

You might notice that in the @RepositoryRestResource annotation you are specifying the /fridge URL context for the generated endpoints.

Test the Mongo Repository and Add Some Data

Stop the app (Control-C, if it’s still running) and re-run it.

./gradlew bootRun

Test the home endpoint again.

$ http :8080

HTTP/1.1 200
Content-Type: application/hal+json;charset=UTF-8
Date: Mon, 16 Dec 2019 03:41:05 GMT
Transfer-Encoding: chunked

{
    "_links": {
        "fridge": {
            "href": "http://localhost:8080/fridge{?page,size,sort}",
            "templated": true
        },
        "profile": {
            "href": "http://localhost:8080/profile"
        }
    }
}

This time you’ll see the /fridge endpoint is listed.

Test it out with http :8080/fridge. You should see a response like the one below:

{
    "_embedded": {
        "fridge": []
    },
    "_links": {
        "profile": {
            "href": "http://localhost:8080/profile/fridge"
        },
        "self": {
            "href": "http://localhost:8080/fridge{?page,size,sort}",
            "templated": true
        }
    },
    "page": {
        "number": 0,
        "size": 20,
        "totalElements": 0,
        "totalPages": 0
    }
}

Not a whole lot going on yet, but that’s easily changed. You’re going to use POST requests to add some data to the embedded MongoDB database. But first, you need to configure an application property.

Add the following line to your src/main/resources/application.properties file.

spring.jackson.date-format=MM-dd-yyyy

This tells Spring the expected date format for the expiration property, which will allow it to properly parse the JSON string into a Java date.

Stop (Control-C) and restart the application.

./gradlew bootRun

Now add some data using the following requests.

http POST :8080/fridge name=milk owner=Andrew expiration=01-01-2020 
http POST :8080/fridge name=cheese owner=Andrew expiration=02-10-2020
http POST :8080/fridge name=pizza owner=Andrew expiration=03-30-2020

Check out the inventory now and you should see these new items.

$ http :8080/fridge

HTTP/1.1 200
Content-Type: application/hal+json;charset=UTF-8
Date: Mon, 16 Dec 2019 03:45:23 GMT
Transfer-Encoding: chunked

{
    "_embedded": {
        "fridge": [
            {
                "_links": {
                    "refrigeratorItem": {
                        "href": "http://localhost:8080/fridge/5dae7b4c6a99f01364de916c"
                    },
                    "self": {
                        "href": "http://localhost:8080/fridge/5dae7b4c6a99f01364de916c"
                    }
                },
                "expiration": "01-01-2020",
                "name": "milk",
                "owner": "Andrew"
            },
            {
                "_links": {
                    "refrigeratorItem": {
                        "href": "http://localhost:8080/fridge/5dae7b4d6a99f01364de916d"
                    },
                    "self": {
                        "href": "http://localhost:8080/fridge/5dae7b4d6a99f01364de916d"
                    }
                },
                "expiration": "02-10-2020",
                "name": "cheese",
                "owner": "Andrew"
            },
            {
                "_links": {
                    "refrigeratorItem": {
                        "href": "http://localhost:8080/fridge/5dae7b4f6a99f01364de916e"
                    },
                    "self": {
                        "href": "http://localhost:8080/fridge/5dae7b4f6a99f01364de916e"
                    }
                },
                "expiration": "03-30-2020",
                "name": "pizza",
                "owner": "Andrew"
            }
        ]
    },
    "_links": {
        "profile": {
            "href": "http://localhost:8080/profile/fridge"
        },
        "self": {
            "href": "http://localhost:8080/fridge{?page,size,sort}",
            "templated": true
        }
    },
    "page": {
        "number": 0,
        "size": 20,
        "totalElements": 3,
        "totalPages": 1
    }
}

Notice that the returns JSON gives you the URL for each individual item. If you wanted to delete the first item in the list above, you could run the following request.

http DELETE :8080/fridge/5dae7b4c6a99f01364de916c

The long string,5dae7b4c6a99f01364de916c, is the unique ID for that item. MongoDB doesn’t use sequential integer ID numbers like SQL databases often do. It uses randomly generated UUIDs instead.

If you wanted to update an item, you could use a PUT, as shown below.

http PUT :8080/fridge/5dae7b4f6a99f01364de916e name="old pizza" expiration="03-30-2020" owner="Erin"

Note that with a PUT you have to send data for all the fields, not just the field you want to update, otherwise the omitted fields are set to null. If you just want to update select fields, use a PATCH.

http PATCH :8080/fridge/5dae7b4f6a99f01364de916e owner="Andrew"

With that rather paltry amount of work, you’ve created a MongoDB database model and exposed it to the world using a REST API. Pretty sweet!

The next step is to secure it. The last thing you need is hackers breaking into your house and stealing your pizza and cheese.

Create an OIDC Application for Your Java + MongoDB App

Okta is a software-as-service identity management provider. We provide solutions that make adding authentication and authorization to web applications easy. In this tutorial, you are going to use Okta to add JSON Web Token authentication and authorization to your application using OAuth 2.0 and OpenID Connect (OIDC).

OAuth 2.0 is an authorization protocol (verifying what the client or user is allowed to do) and OIDC is an authentication protocol (verifying the identity of the user) built on top of OAuth 2.0. They are a set of open standards that help ensure your web application’s security is handled safely and effectively. Together they provide a complete authentication and authorization protocol.

They are not, however, implementations. That’s where Okta comes in. Okta will be the identity provider and your Spring Boot app will be the client.

You should have already signed up for a free developer account at Okta. Navigate to the developer dashboard at https://developer.okta.com. If this is your first time logging in, you may need to click the Admin button.

To configure JSON Web Token (JWT) authentication and authorization, you need to create an OIDC application.

From the top menu, click on the Applications button. Click the Add Application button.

Select application type Web and click Next.

Give the app a name. I named mine “Spring Boot Mongo”.

Under Login redirect URIs, add a new URI: https://oidcdebugger.com/debug.

Under Grant types allowed, check Implicit (Hybrid).

The rest of the default values will work.

Click Done.

Leave the page open or take note of the Client ID. You’ll need it in a bit when you generate a token.

To test the REST API, you’re going to use the OpenID Connect Debugger to generate a token. This is why you need to add the login redirect URI and allow the implicit grant type.

Configure Spring Boot for OAuth 2.0

Now you need to update the Spring Boot application to use JWT authentication. First, open your src/main/resources/build.gradle file and uncomment the okta-spring-boot-starter dependency.

dependencies {  
    ...
    implementation 'com.okta.spring:okta-spring-boot-starter:1.3.0'  <-- UNCOMMENT ME
    ... 
}

Next, open your src/main/resources/application.properties file and add your Okta Issuer URI to it. The Issuer URI can be found by opening your Okta developer dashboard. From the top menu, select API and Authorization Servers. Your Issuer URI can be found in the panel in the row for the default authorization server.

spring.jackson.date-format=MM-dd-yyyy  
okta.oauth2.issuer=https://{yourOktaUrl}/oauth2/default

The last update is to add a new class called SecurityConfiguration.

src/main/java/com/okta/mongodb/mongodboauth/SecurityConfiguration.java

package com.okta.mongodb.mongodboauth;  

import org.springframework.context.annotation.Configuration;  
import org.springframework.security.config.annotation.web.builders.HttpSecurity;  
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;  

@Configuration  
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {  

    @Override  
    public void configure (HttpSecurity http) throws Exception {  
        http.authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .oauth2ResourceServer()
            .jwt();
    }
}

This simple class configures Spring Boot to authenticate all requests and to use an OAuth 2.0 resource server with JWT authentication and authorization.

Now if you restart the application and try a request, you’ll get a 401.

$ http :8080

HTTP/1.1 401
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 0
...

This is the expected response. You’re REST API is now protected and requires a valid token.

Generate a Token Using the OpenID Connect Debugger

To access your now-protected server, you need a valid JSON Web Token. The OIDC Debugger is a handy page that will allow you to generate a JWT.

Open the OIDC Debugger.

You will need to fill in the following values.

  • Authorization URI: https://{yourOktaUrl}/oauth2/default/v1/authorize
  • Client ID: the Client ID from your Okta OIDC application
  • State: just fill in any non-blank value (this is used in production to help protect against cross-site forgery attacks)
  • Response type: check box for token

The rest of the default values should work. Scroll down to the bottom and click Send Request.

If all went well, you will see your brand new access token.

Copy the token to your clipboard and store it in a shell variable like so:

TOKEN=eyJraWQiOiJrQkNxZ3o1MmQtOUhVSl94c0x4aGtzYlJxUDVD...

Now you can make authenticated and authorized requests.

$ http :8080 "Authorization: Bearer $TOKEN"

HTTP/1.1 200
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
...

{
    "_links": {
        "fridge": {
            "href": "http://localhost:8080/fridge{?page,size,sort}",
            "templated": true
        },
        "profile": {
            "href": "http://localhost:8080/profile"
        }
    }
}

In this tutorial, you created a Java data model class and mapped it to a MongoDB domain document using Spring Data annotations. You used a simple embedded MongoDB database as the datastore. You used Spring Boot to quickly and easily expose your data model via a REST API. Finally, you secured the REST API using Okta and Okta’s Spring Boot Starter.

The source code for this tutorial is available on GitHub at oktadeveloper/okta-java-mongodb-example.

Java Reflection API Tutorial

Java Reflection API Tutorial

Reflection API in Java is used to manipulate class and its members which include fields, methods, constructor, etc. at runtime. One advantage of reflection API in Java is, it can manipulate private members of the class too

What is Reflection in Java?

Java Reflection is the process of analyzing and modifying all the capabilities of a class at runtime. Reflection API in Java is used to manipulate class and its members which include fields, methods, constructor, etc. at runtime.

One advantage of reflection API in Java is, it can manipulate private members of the class too.

The java.lang.reflect package provides many classes to implement reflection java.Methods of the java.lang.Class class is used to gather the complete metadata of a particular class.

Class in java.lang.reflect Package

Following is a list of various Java classes in java.lang.package to implement reflection-

Field: This class is used to gather declarative information such as datatype, access modifier, name and value of a variable.

Method: This class is used to gather declarative information such as access modifier, return type, name, parameter types and exception type of a method.

Constructor: This class is used to gather declarative information such as access modifier, name and parameter types of a constructor.

Modifier: This class is used to gather information about a particular access modifier.

Methods used in java.lang.Class

Public String getName (): Returns the name of the class.

Public Class getSuperclass(): Returns the super class reference

Public Class[] getInterfaces() : Returns an array of interfaces implemented by the specified class

Public in getModifiers (): Returns an integer value representing the modifiers of the specified class which needs to be passed as a parameter to "public static String toString (int i )" method which returns the access specifier for the given class.

How to get complete information about a class

To get information about variables, methods, and constructors of a class, we need to create an object of the class.

public class Guru99ClassObjectCreation {
	public static void main (String[] args) throws ClassNotFoundException {
		//1 - By using Class.forname() method 
		Class c1 = Class.forName("Guru99ClassObjectCreation"); 
		//2- By using getClass() method 
		Guru99ClassObjectCreation guru99Obj = new Guru99ClassObjectCreation();
		Class c2 = guru99Obj.getClass();
		//3- By using .class 
		Class c3= Guru99ClassObjectCreation.class;
		}
	}

Following example shows different ways to create object of class "class" :

Example 1 : How to get Metadata of Class

Following example shows how to get metadata such as: Class name, super class name, implemented interfaces, and access modifiers of a class.

We will get the metadata of below class named Guru99Base.class:

import java.io.Serializable;
public abstract class Guru99Base implements Serializable,Cloneable {
}
  1. Name of the class is: Guru99Base
  2. It's access modifiers are: public and abstract
  3. It has implemented interfaces: Serializable and Cloneable
  4. Since it has not extended any class explicitly, it's super class is: java.lang.Object

Below class will get the meta data of Guru99Base.class and print it:

import java.lang.reflect.Modifier;
public class Guru99GetclassMetaData {
public static void main (String [] args) throws ClassNotFoundException { 
// Create Class object for Guru99Base.class 
Class guru99ClassObj = Guru99Base.class;

// Print name of the class 
system.out.println("Name of the class is : " +guru99ClassObj.getName());

// Print Super class name
system.out.println("Name of the super class is : " +guru99ClassObj.getSuperclass().getName());

// Get the list of implemented interfaces in the form of Class array using getInterface() method
class[] guru99InterfaceList = guru99classObj.getInterfaces();

// Print the implemented interfaces using foreach loop 
system.out.print("Implemented interfaces are : ");
for (Class guru99class1 : quru99 InterfaceList)	{
	system.out.print guru99class1.getName() + " ");
}
system.out.println();

//Get access modifiers using get Modifiers() method and toString() method of java.lang.reflect.Modifier class
int guru99AccessModifier= guru99classObj.getModifiers(); 
// Print the access modifiers
System.Out.println("Access modifiers of the class are : " +Modifier.tostring(guru99AccessModifier));

}

}

  1. print the name of the class using getName method
  2. Print the name of the super class using getSuperClass().getName() method
  3. Print the name of the implemented interfaces
  4. Print the access modifiers used by the class

Example 2 : How to get Metadata of Variable

Following examples shows how to get metadata of variable:

Here, we are creating a class named Guru99VariableMetaData .class with some variables:

package guru;
public class Guru99VariableMetaData {
public static int guru99IntVar1=1111;
static int guru99IntVar2=2222;
static String guru99StringVar1="guru99.com";
static String guru99StringVar2="Learning Reflection API";
}

Steps to get the metadata about the variables in the above class:

Create the class object of the above class i.e. Guru99VariableMetaData.class as below:

  Guru99VariableMetaData  guru99ClassVar  = new Guru99VariableMetaData();
Class guru99ClassObjVar = guru99ClassVar.getClass();

Get the metadata in the form of field array using getFields() or getDeclaredFields() methods as below:

Field[]  guru99Field1= guru99ClassObjVar .getFields();
Field[] guru99Fiel2= guru99ClassObjVar .getDeclaredFields();

getFields() method returns metadata of the public variable from the specified class as well as from its super class.

getDeclaredFields() method returns metadata of the all the variables from the specified class only.

  1. Get the name of the variables using "public String getName()" method.
  2. Get the datatype of the variables using "public Class getType()" method.
  3. Get the value of the variable using "public xxx get (Field)" method.
  4. Here, xxx could be a byte or short of any type of value we want to fetch.
  5. Get the access modifiers of the variables using getModifier() and Modifier.toString(int i) methods.
  6. Here, we are writing a class to get the metadata of the variables present in the class Guru99VariableMetaData .class:
package guru;
import java.lang.reflect.Field;

public class Guru99VariableMetaDataTest {
public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
// Create Class object for Guru99VariableMetaData.class
Guru99VariableMetaData guru99ClassVar = new Guru99VariableMetaData();
Class guru99ClassObjVar = guru99ClassVar.getClass();

// Get the metadata of all the fields of the class Guru99VariableMetaData 
Field[] guru99Field1= guru99ClassObjVar.getDeclaredFields();

// Print name, datatypes, access modifiers and values of the varibales of the specified class 
for(Field field : guru99Field1) { 
System.out.println("Variable name : "+field.getName());
System.out.println("Datatypes of the variable :"+field.getType());

int guru99AccessModifiers = field.getModifiers();
System.out.printlln("Access Modifiers of the variable : "+Modifier.toString(guru99AccessModifiers));
System.out.println("Value of the variable : "+field.get(field));
System.out.println();
system.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *") ;
}
}

}

  1. Created class object for Guru99VariableMetaData.class
  2. Got all the metadata of the variables in a Field array
  3. Printed all the variable names in the class Guru99VariableMetaData.class
  4. Printed all the data types of the variables in the class Guru99VariableMetaData.class
  5. Printed all the access modifiers of the variables in the class Guru99VariableMetaData.class
  6. Printed values of all the variables in Printed all the data types of the variables in the class Guru99VariableMetaData.class
Example 3 : How to get Metadata of Method
  1. Following examples shows how to get metadata of a method:
  2. Here, we are creating a class named Guru99MethodMetaData .class with some methods
package guru;		
import java.sql.SQLException;
public class Guru99MethodMetaData {

public void guru99Add(int firstElement, int secondElement , String result) 									
throws ClassNotFoundException, ClassCastException{			
      System.out.println("Demo method for Reflextion  API");					
}	
public String guru99Search(String searchString) 			
throws ArithmeticException, InterruptedException{			
    System.out.println("Demo method for Reflection API");					
	return null;					
}	
public void guru99Delete(String deleteString) 					
throws SQLException{			
    System.out.println("Demo method for Reflection API");					
}	

}

Steps to get the metadata about the methods in the above class :

Create the class object of the above class i.e. Guru99MethodMetaData.class as below:

Guru99MethodMetaData  guru99ClassVar  = new Guru99MethodMetaData  ();
Class guru99ClassObjVar = guru99ClassVar.getClass();

Get method information in a Method array using getMethods() and getDeclaredMethods() method as below:

Method[]  guru99 Method 1= guru99ClassObjVar .get Methods();
Method [] guru99 Method 2= guru99ClassObjVar .getDeclared Method s();

getMethods() method returns metadata of the public methods from the specified class as well as from its super class.

getDeclaredMethods() method returns metadata of the all the methods from the specified class only.

Get the name of the method using getName() method.

Get the return type of the method using getReturnType() method.

Get access modifiers of the methods using getModifiers() and Modifiers.toString(int i) methods.

Get method parameter types using getParameterTypes() method which returns a class array.

Get thrown exception using getExceptionTypes() method which returns a class array.

Here, we are writing a class to get the metadata of the methods present in the class Guru99MethodMetaData.class:

package guru;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Guru99MethodMetaDataTest {

public static void main (String[] args) {
	// Create Class object for Guru99Method MetaData.class 
	class guru99ClassObj = Guru99MethodMetaData.class;

	// Get the metadata or information of all the methods of the class using getDeclaredMethods() 
	Method[] guru99Methods=guru99classObj.getDeclaredMethods();

	for(Method method : guru99Methods) { 
	// Print the method names
	System.out.println("Name of the method : "+method.getName());
	
	// Print return type of the methods 
	System.out.println("Return type of the method : "+method.getReturnType());
	
	//Get the access modifier list and print
	int guru99ModifierList = method.getModifiers(); 
	System.Out.printlin ("Method access modifiers : "+Modifier.toString(guru99ModifierList));
	
	// Get and print parameters of the methods 
	Class[] guru99ParamList= method.getParameterTypes(); 
	system.out.print ("Method parameter types : "); 
	for (Class class1 : guru99ParamList){ 
		System.out.println(class1.getName()+" ");
	}
    System.out.println();
	
	// Get and print exception thrown by the method 
	Class[] guru99ExceptionList = method. getExceptionTypes(); 
	system.out.print("Excpetion thrown by method :"); 
	for (Class class1 : guru99ExceptionList) {
		System.out.println (class1.getName() +" "):
	} 
	System.Out.println(); 
	system.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ");
	
	}

}

}

Created class object for Guru99MethodMetaData.class

Got all the metadata of all the methods in a Method array

Printed all the method names present in the class Guru99MethodMetaData.class

Printed return types of the methods in the class Guru99MethodMetaData.class

Printed all the access modifiers of the methods in the class Guru99MethodMetaData.class

Printed parameter types of the methods in Guru99MethodMetaData.class

Printed exceptions are thrown by methods in Guru99MethodMetaData.class

Example 4 : How to get Metadata of Constructors
  1. Following examples shows how to get metadata of constructors:
  2. Here, we are creating a class named Guru99Constructor.class with different constructors:
package guru;

import java.rmi.RemoteException;
import java.sql.SQLException;

public class Guru99Constructor {

public Guru99Constructor(int no) throws ClassCastException ,ArithmeticException{  }							
public Guru99Constructor(int no, String name) throws RemoteException ,SQLException{  }							
public Guru99Constructor(int no, String name, String address) throws InterruptedException{  }							

}

Here, we are writing a class to get the metadata of the constructors present in the class Guru99Constructor.class:

package guru;
import java.lang.reflect.Constructor;
public class Guru99ConstructorMetaDataTest {

public static void main (String[] args) {
	// Create Class object for Guru99Constructor.class 
	Class guru99Class=Guru99Constructor.class;

	// Get all the constructor information in the Constructor array
	Constructor[] guru99ConstructorList = guru99Class.getConstructors();
	
	for (Constructor constructor : guru99ConstructorList) {
		// Print all name of each constructor
		System.out.println("Constrcutor name : "+constructor.getName());
		
		//Get and print access modifiers of each constructor 
		int guru99Modifiers= constructor.getModifiers(); 
		System.Out.printlin ("Constrctor modifier : "+Modifier.toString(guru99Modifiers));
		
		// Get and print parameter types 
		Class[] guru99ParamList=constructor.getParameterTypes();
		System.out.print ("Constrctor parameter types :"); 
		for (Class class1 : guru99ParamList) { 
			System.out.println(class1.getName() +" ");
		}
		System. out.println();

		// Get and print exception thrown by constructors
		Class[] guru99ExceptionList=constructor.getFxceptionTypes();
		System.out.println("Exception thrown by constructors :"); 
		for (Class class1 : guru99ExceptionList) { 
			System.out.println(class1.getName() +" ");
		} 
		System.out.println();
		System.out.println("*******************************************");
	}
}

}

  1. Created class object for Guru99Constructor.class
  2. Got all the metadata of all the constructors in a Constructor array
  3. Printed all the constructor's names present in the class Guru99Constructor.class
  4. Printed all the access modifiers of the constructors in the class Guru99Constructor.class
  5. Printed parameter types of the constructors in Guru99Constructor.class
  6. Printed exceptions are thrown by constructors in Guru99Constructor.class
Summary:
  • Reflection programming in java helps in retrieving and modifying information about Classes and Class members such variable, methods, constructors.
  • Reflection API in Java can be implemented using classes in java.lang.reflect package and methods of java.lang.Class class.
  • Some commonly used methods of java.lang.Class class are getName (), getSuperclass (), getInterfaces (), getModifiers () etc.
  • Some commonly used classes in java.lang.reflect package are Field, Method, Constructor, Modifier, etc.
  • Reflection API can access private methods and variables of a class which could be a security threat.
  • Reflection API is a powerful capability provided by Java, but it comes with some overheads such as slower performance, security vulnerability, and permission issue. Hence, reflection API should be treated as the last resort to performing an operation.


Thanks for reading. If you liked this post, share it with all of your programming buddies!

Originally published on guru99.com

Test a REST API with Java

Test a REST API with Java

This tutorial focuses on the basic principles and mechanics of testing a REST API with live Integration Tests (with a JSON payload).

This tutorial focuses on the basic principles and mechanics of testing a REST API with live Integration Tests (with a JSON payload).

1. Overview

The main goal is to provide an introduction to testing the basic correctness of the API – and we’re going to be using the latest version of the GitHub REST API for the examples.

For an internal application, this kind of testing will usually run as a late step in a Continuous Integration process, consuming the REST API after it has already been deployed.

When testing a REST resource, there are usually a few orthogonal responsibilities the tests should focus on:

  • the HTTP response code
  • other HTTP headers in the response
  • the payload (JSON, XML)

Each test should only focus on a single responsibility and include a single assertion. Focusing on a clear separation always has benefits, but when doing this kind of black box testing is even more important, as the general tendency is to write complex test scenarios in the very beginning.

Another important aspect of the integration tests is adherence to the Single Level of Abstraction Principle – the logic within a test should be written at a high level. Details such as creating the request, sending the HTTP request to the server, dealing with IO, etc should not be done inline but via utility methods.

2. Testing the Status Code
@Test
public void givenUserDoesNotExists_whenUserInfoIsRetrieved_then404IsReceived()
  throws ClientProtocolException, IOException {
  
    // Given
    String name = RandomStringUtils.randomAlphabetic( 8 );
    HttpUriRequest request = new HttpGet( "https://api.github.com/users/" + name );
 
    // When
    HttpResponse httpResponse = HttpClientBuilder.create().build().execute( request );
 
    // Then
    assertThat(
      httpResponse.getStatusLine().getStatusCode(),
      equalTo(HttpStatus.SC_NOT_FOUND));
}

This is a rather simple test – it verifies that a basic happy path is working, without adding too much complexity to the test suite.

If for whatever reason, it fails, then there is no need to look at any other test for this URL until this is fixed.

3. Testing the Media Type
@Test
public void
givenRequestWithNoAcceptHeader_whenRequestIsExecuted_thenDefaultResponseContentTypeIsJson()
  throws ClientProtocolException, IOException {
  
   // Given
   String jsonMimeType = "application/json";
   HttpUriRequest request = new HttpGet( "https://api.github.com/users/eugenp" );
 
   // When
   HttpResponse response = HttpClientBuilder.create().build().execute( request );
 
   // Then
   String mimeType = ContentType.getOrDefault(response.getEntity()).getMimeType();
   assertEquals( jsonMimeType, mimeType );
}

This ensures that the Response actually contains JSON data.

As you might have noticed, we’re following a logical progression of tests – first the Response Status Code (to ensure that the request was OK), then the Media Type of the Response, and only in the next test will we look at the actual JSON payload.

4. Testing the JSON Payload
@Test
public void
  givenUserExists_whenUserInformationIsRetrieved_thenRetrievedResourceIsCorrect()
  throws ClientProtocolException, IOException {
  
    // Given
    HttpUriRequest request = new HttpGet( "https://api.github.com/users/eugenp" );
 
    // When
    HttpResponse response = HttpClientBuilder.create().build().execute( request );
 
    // Then
    GitHubUser resource = RetrieveUtil.retrieveResourceFromResponse(
      response, GitHubUser.class);
    assertThat( "eugenp", Matchers.is( resource.getLogin() ) );
}

In this case, I know the default representation of GitHub resources is JSON, but usually, the Content-Type header of the response should be tested alongside the Accept header of the request – the client asks for a particular type of representation via Accept, which the server should honor.

5. Utilities for Testing

We’re going to use Jackson 2 to unmarshall the raw JSON String into a type-safe Java Entity:

public class GitHubUser {
 
    private String login;
 
    // standard getters and setters
}

We’re only using a simple utility to keep the tests clean, readable and at a high level of abstraction:

public static <T> T retrieveResourceFromResponse(HttpResponse response, Class<T> clazz)
  throws IOException {
  
    String jsonFromResponse = EntityUtils.toString(response.getEntity());
    ObjectMapper mapper = new ObjectMapper()
      .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    return mapper.readValue(jsonFromResponse, clazz);
}

Notice that Jackson is ignoring unknown properties that the GitHub API is sending our way – that’s simply because the Representation of a User Resource on GitHub gets pretty complex – and we don’t need any of that information here.

6. Dependencies

The utilities and tests make use of the following libraries, all available in Maven central:

7. Conclusion

This is only one part of what the complete integration testing suite should be. The tests focus on ensuring basic correctness for the REST API, without going into more complex scenarios,

For example, the following are not covered: Discoverability of the API, consumption of different representations for the same Resource, etc.

The implementation of all these examples and code snippets can be found over on Github – this is a Maven-based project, so it should be easy to import and run as it is.