Java REST API + cURL + python3

During the next lines, I am going to implement a very simple REST API using JavaEE 7 and Java SE 8 technologies, maven as build tool and GlassFish as application server. I am going to test this API with cURL and, I am going to consume this API using python3 using the Requests module.

Java EE 7 REST API

First, we need to create a maven project in our favorite IDE and add our dependencies to the pom.xml file

...
<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <failOnMissingWebXml>false</failOnMissingWebXml>
</properties>

<dependencies>
    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>eclipselink</artifactId>
        <version>2.5.2</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId>
        <version>2.5.2</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-api</artifactId>
        <version>7.0</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

<build>
    <finalName>apicrud</finalName>
</build>
...

Second, we are going to create a persistence.xml file. In this case, we are not interested in how to configure a DB, then, we are going to use the default datasource that GlassFish provides us as default “jdbc/__default“. With all of this in mind, the file should look like this:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
        http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="ApiCrudPU" transaction-type="JTA">
        <jta-data-source>jdbc/__default</jta-data-source>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>
            <property name="javax.persistence.schema-generation.database.action" value="create"/>
        </properties>
    </persistence-unit>
</persistence>

Now, we need to create our Entity. In this case, I have chosen a simple one, User with three attributes:

  • id: Autogenerated id to identify the user.
  • name: User’s name.
  • email: User’s email.

The result should be something like:

package com.wordpress.binarycoders.apicrud;

import java.io.Serializable;
import java.util.Objects;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;

@Entity
@Table (name = "users")
@NamedQueries ({
    @NamedQuery (name = User.FIND_ALL, query = "SELECT u FROM User u")
})
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class User implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    public static final String FIND_ALL = "User.findAll";
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    
    @Column(name = "name")
    private String name;
    
    @Column(name = "email")
    private String email;

    /* Getters, Setters, equals and hashCode methods */    
}

The next step, it is to implement the boundary or service layer. Being a simple example, we can skip this layer, but I like to implement everything for learning purposes. This layer is going to be very simple, only the necessary object to perform the operation in the DB and the basic operations to implement a CRUD. The result looks like:

package com.wordpress.binarycoders.apicrud;

import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.validation.constraints.NotNull;

@Stateless
public class UserService {
    
    @PersistenceContext
    private EntityManager em;
    
    public void create(@NotNull User user) {
        this.em.persist(user);
    }
    
    public User findById(@NotNull Long id) {
        return this.em.find(User.class, id);
    }
    
    public List<User> findAll() {
        TypedQuery<User> typedQuery = this.em.createNamedQuery(User.FIND_ALL, User.class);

        return typedQuery.getResultList();
    }
    
    public void update(@NotNull User user) {
        this.em.merge(user);
    }
    
    public void delete(@NotNull Long id) {
        this.em.remove(this.findById(id));
    }
}

To do all of this available to the world, we need to implement our REST API, and for this, we need to configure the REST capabilities in our system, piece of cake with the last version of Java EE. We just need to create a class to enable these capabilities:

package com.wordpress.binarycoders.apicrud;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/rs")
public class ApplicationConfig extends Application {
    
}

And, finally, we need to implement our REST layer with the four actions that are going to allow us to perform the CRUD operations:

package com.wordpress.binarycoders.apicrud;

import java.net.URI;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

@Path("/users")
@Produces ({ MediaType.APPLICATION_JSON })
@Consumes ({ MediaType.APPLICATION_JSON })
@Stateless
public class UserEndPoint {
    
    @EJB
    private UserService service;
    
    @Context
    private UriInfo uriInfo;
    
    @GET
    public Response findAll() {
        List<User> users = this.service.findAll();
        
        GenericEntity<List<User>> list = new GenericEntity<List<User>>(users) {};
        
        return Response.ok(list).build();
    }
    
    @GET
    @Path("/{id}")
    public Response findById(@PathParam("id") Long id) {
        User user = this.service.findById(id);
        
        if (user == null) {
            throw new NotFoundException();
        }
        
        return Response.ok(user).build();
    }
    
    @POST
    public Response create(User user) {
        this.service.create(user);
        
        URI uri = uriInfo.getAbsolutePathBuilder().path(String.valueOf(user.getId())).build();
        
        return Response.created(uri).build();
    }
    
    @PUT
    public Response update(User user) {
        this.service.update(user);
        
        return Response.ok().build();
    }
    
    @DELETE
    @Path("/{id}")
    public Response delete(@PathParam("id") Long id) {
        this.service.delete(id);
        
        return Response.noContent().build();
    }
}

I think that in this point, assuming that everyone reading this, it is a developer and this is not an entry level post, all of you should be capable to understand everything has been written in the above lines. If there are things that you do not know or you do not understand due to a lack of information or your knowledge is not enough (all of us have been there), look at the note at the end of this post.

cURL test

Now, obviously, we need to test if our REST API is working properly. For this, we can implement some solution based on test frameworks or manual code but, due to the simplicity of the object User, it is enough with the cURL tool. To test our API we are going to perform these operations:

  • Select all the users
  • Create a user
  • Select the created user
  • Update the user
  • Delete the user

These operations can be performed with the next commands:

curl -i -H "Content-Type: application/json" http://localhost:8080/ApiCRUD/rs/users
curl -i -H "Content-Type: application/json" -X POST -d '{"name":"john","email":"john@example.org"}' http://localhost:8080/ApiCRUD/rs/users
curl -i -H "Content-Type: application/json" http://localhost:8080/ApiCRUD/rs/users/1
curl -i -H "Content-Type: application/json" -X PUT -d '{"id”:1,”name":"John Doe","email":"john.doe@example.org"}' http://localhost:8080/ApiCRUD/rs/users
curl -i -H "Content-Type: application/json" -X DELETE http://localhost:8080/ApiCRUD/rs/users/1

Everything should look well, and the appropriate HTTP codes should be received.

Python3 client

The last step today, it is to implement a very very simple python3 client to consume our API. This is going to be a basic script to invoke the CRUD operations available in the API.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import requests
import json

URL = 'http://localhost:8080/ApiCRUD/rs/users'

def getUsers():
	print('Get users...\n')

	response = requests.get(URL)

	assert response.status_code == 200

	users = response.json()
	print(json.dumps(users, indent = 4, separators = (',', ':')))

def getUser(location):
	print('Get single user ...\n')

	response = requests.get(location)

	assert response.status_code == 200

	users = response.json()
	print(json.dumps(users, indent = 4, separators = (',', ':')))

def createUser():
	print('Creating user...\n')

	headers = {'content-type': 'application/json'}
	user = {"name": "John Doe", "email": "john.doe@example.org"}
	response = requests.post(URL, data = json.dumps(user), headers = headers)

	assert response.status_code == 201

	print('Location: ' + response.headers['location'])

	return response.headers['location']

def updateUser(location):
	print('Updating user...')

	loc = location.split('/')

	headers = {'content-type': 'application/json'}
	user = {"id": loc[-1], "name": "Jane Doe", "email": "jane.doe@example.org"}
	response = requests.put(URL, data = json.dumps(user), headers = headers)

	assert response.status_code == 200

def deleteUser(location):
	print('Deleting user...')

	response = requests.delete(location)

	assert response.status_code == 204

	print('Checking delete operation')
	response = requests.get(location)

	assert response.status_code == 404

def main():
	getUsers()
	location = createUser()
	getUser(location)
	updateUser(location)
	getUser(location)
	deleteUser(location)

if __name__ == "__main__":
	main()

And that’s all. Now, we have a little REST AP, a python3 client and a basic knowledge about how to use cURL to test it.

See you.

You can find the code for the REST API available here.

Note: All the content in this post will be splitter and explained in future post, one for each one of the three big point explained in here: Java EE 7 REST API creation, cURL test and python3 REST client.

Advertisements
Java REST API + cURL + python3

Creating a basic datasource in Glassfish 4

Today we are going to see how to create a datasource in our Glassfish server in a few steps. In this case, it is going to be for a MySQL database:

First of all, if we have not done yet, we should copy the MySQL driver in our folder lib inside the domain folder where we are going to deploy our application. After that, let’s start to configure our datasource.

As default, the admin console for Glassfish server is in the port 4848. You should be able to see this admin console connecting to your server with this port. In my case, I have the server installed in my own machine, then, my URL to connect to the admin console looks like this:

http://localhost:4848/

If the connections is performed correctly, the browser should prompt you asking for the admin credentials, and after introduce them correctly, you should see the admin console with a menu in the left side.

In this menu, we are going to open the category:

Resources -> JDBC

Under this category, you should find two more categories:

  • JDBC Resources
  • JDBC Connection Pools

Let’s open the JDBC Connection Pools category and click in New… to create a new connection pool for our datasource.

Here, we can see that the process to create a new connection pool has two steps. We should introduce the following data:

In the first step:

  • Name: In my case, ExamplePool.
  • Resource type: We should select javax.sql.DataSource from the dropdown list.
  • Database Driver Vendor: We should select MySql for this example.

In the second step you can accept all the default values and go directly to the Additional Properties table. Here, the best option, specially if we want a full control of everything, we can delete all the properties in there, and define new properties. In this case, we are only go to add the basic ones to connect to our database, but there are a lot of different properties that can be added. Then, let’s add our properties:

  • User: The user to connect to de DB. In my case, dbuser
  • Password: The user’s password to connect. In my case, resudb. In this case, MySQL allows us to have users without passwords, but Glassfish is going to return an error if the user does not have a password. Then, if your user does not have a password, you should set one. *
  • Url: The URL to connect to our schema. In this case, I am using the schema example. The URL to connect, in my case, looks like: jdbc:mysql://localhost:3306/example

In most cases, setting these properties is enough, but I have detected that there are IDEs where is not enough. In this case, as a precaution, we can set an extra property to avoid future problems:

  • driverClass: In this case, the MySQL driver class com.mysql.jdbc.Driver

Now, it is time to save our pool. After that, if you click in the left menu in the pool’s name, you will see the configuration of the pool in the main page and a new button labeled as Ping. Let’s click on it to confirm that the configuration is correctly done. If everything goes well, a message Ping Succeeded should be shown.

Now that our pool is ready, we should create our datasource. For this, we should click in the left menu in the JDBC Resources category and click in the New… button. In here, we only need to add the JNDI name, in general, something like jdbc/example and choose in the dropdown list the pool name that we have previously created (ExamplePool). After that, we can save it and, we are ready to go.

That’s all. Now, we only need to use our new datasource in our applications.

See you.

* To set a password for a MySQL user we should execute:

UPDATE mysql.user
   SET user.Password = PASSWORD('newPassword')
 WHERE user.User = 'username';
Creating a basic datasource in Glassfish 4