[JAX-RS] Some good auth resources

http://stackoverflow.com/questions/26777083/best-practice-for-rest-token-based-authentication-with-jax-rs-and-jersey

http://www.developerscrappad.com/1814/java/java-ee/rest-jax-rs/java-ee-7-jax-rs-2-0-simple-rest-api-authentication-authorization-with-custom-http-header/

https://jersey.java.net/documentation/latest/security.html

https://www.ibm.com/support/knowledgecenter/SSAW57_8.5.5/com.ibm.websphere.nd.doc/ae/twbs_jaxrs_impl_securejaxrs_webcont.html

 

 

 

[JAX-RS] Simple Server and Client using Jersey 1.19 Client API (JSON)

Using Jersey 1.19. in general 1.xx vs 2.xx – the package names differ and some of the Client API methods and ways to get the Client.
Note that the server here is a Dynamic Java Application running on Glassfish 4 so the dependencies are added automatically while the client is a maven project.

1. The server Application:

package com.vvirlan;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath("rest")
public class RestApplication extends Application {
	@Override
	public Set<Class<?>> getClasses() {
		Set<Class<?>> classes = new HashSet<>();
		classes.add(ResourceOne.class);
		return classes;
	}
}

2. Server Resource:

package com.vvirlan;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
@Path("one")
public class ResourceOne {
	@POST
	@Path("hello")
	@Produces(MediaType.APPLICATION_JSON)
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public MyBean sayJsonHello(@FormParam("x") String x, @FormParam("y") String y) {
		System.out.println("X is " +x+" Y is "+y);
		MyBean bean = new MyBean();
		bean.setName("Bob How "+x);
		bean.setAge(120);
		return bean;
	}
}

3. The bean:

package com.vvirlan;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class MyBean {
	private String name;
	private Integer age;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
}

4. Client (a simple Maven project):

package com.vvirlan;
import javax.ws.rs.core.MediaType;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.representation.Form;
public class JaxRsClientApi {
	public static void main(String[] args) {
		JaxRsClientApi client = new JaxRsClientApi();
		client.run();
	}
	public void run() {
		Client client = Client.create();
		WebResource resource = client.resource("http://localhost:8080/JaxRsSimpleServer/rest/one/hello");
		Form form = new Form();
		form.add("x", "XFOO");
		form.add("y", "YBAR");
		MyBean bean = resource
				.type(MediaType.APPLICATION_FORM_URLENCODED_TYPE)
				.accept(MediaType.APPLICATION_JSON_TYPE)
				.post(MyBean.class, form);
		System.out.println(bean);
	}
}

5. The bean on the client side (ideally need to share it somehow)

package com.vvirlan;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class MyBean {
	private String name;
	private Integer age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "MyBean [name=" + name + ", age=" + age + "]";
	}
}

6. Client pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.vvirlan</groupId>
	<artifactId>jaxrsclientapi</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>
		<jersey.version>1.19</jersey.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>com.sun.jersey</groupId>
			<artifactId>jersey-client</artifactId>
			<version>${jersey.version}</version>
		</dependency>

		<dependency>
			<groupId>com.sun.jersey</groupId>
			<artifactId>jersey-json</artifactId>
			<version>${jersey.version}</version>
		</dependency>
	</dependencies>
</project>

[JAX-RS] Implementing custom MessageBodyWriter for serialization

Say you want to serialize your object in a custom format. For XML you can use JAXB, for JSON you can use Jackson. But in case you have your own specific format, you need to implement your own MessageBodyWriter.

1. Maven web application – pom.xml (here jersey 1.19, feel free to upgrade):

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.vvirlan</groupId>
	<artifactId>streamingoutput</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>streamingoutput Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>com.sun.jersey</groupId>
			<artifactId>jersey-server</artifactId>
			<version>1.19</version>
		</dependency>
		<dependency>
			<groupId>com.sun.jersey</groupId>
			<artifactId>jersey-grizzly2</artifactId>
			<version>1.19</version>
		</dependency>

	</dependencies>
	<build>
		<finalName>streamingoutput</finalName>
	</build>
</project>

2. Application class. Note that besides the actual resource class, you need to also add your custom writer.

package com.vvirlan;

import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import com.vvirlan.resources.CustomerResource;
import com.vvirlan.resources.MyCustomWriter;

@ApplicationPath("rest")
public class Application extends javax.ws.rs.core.Application{
	@Override
	public Set<Class<?>> getClasses() {
		Set<Class<?>> classes = new HashSet<Class<?>>();
		classes.add(CustomerResource.class);
		classes.add(MyCustomWriter.class);
		return classes;
	}
}

3. The resource class (CustomerResource):

package com.vvirlan.resources;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("customers")
@Produces(MediaType.TEXT_PLAIN)
public class CustomerResource {
	@GET
	@Path("c")
	@Pretty
	public Customer getCustomer() {
		return new Customer("A",2,2);
	}
}

4. The Customer object:

package com.vvirlan.resources;

//My custom annotation (makes it eligible for my serialization)
@MyContent
public class Customer {

	private String name;
	private int age;
	private int size;

//Mandatory
	public Customer() {

	}

	public Customer(String name, int age, int size) {
		this.name = name;
		this.age = age;
		this.size = size;
	}

	// Getters and setters
}

5. My MyContent annotation

package com.vvirlan.resources;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyContent {

}

6. The actual custom body writer:

package com.vvirlan.resources;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlRootElement;

@Provider
@Produces(MediaType.TEXT_PLAIN)
public class MyCustomWriter implements MessageBodyWriter<Customer> {

	public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
		boolean present = type.isAnnotationPresent(MyContent.class);
		return present;
	}

	public long getSize(Customer t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
		// Leave it to Jersey to put content-length
		return -1;
	}

	public void writeTo(Customer t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
			MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
					throws IOException, WebApplicationException {

		// Here reflection may be used to get the custom serialization
		StringBuilder sb = new StringBuilder();
		sb.append("Name: " + t.getName() + " Age: " + t.getAge() + " Size: " + t.getSize());

		entityStream.write(sb.toString().getBytes());

	}
}

7. Accessing the application at:
http://localhost:8080/yourprojectname/rest/customers/c/

And you will see:
Name: A Age: 2 Size: 2

[JAX-RS] ExceptionMapper example (Maven + Jersey + Glassfish)

Create a new Maven project (Web app archetype) in eclipse and add the dependencies on jersey. Also you will need Glassfish server.
1. pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.vvirlan</groupId>
	<artifactId>rsexampleresponse</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>rsexampleresponse Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>com.sun.jersey</groupId>
			<artifactId>jersey-server</artifactId>
			<version>1.19</version>
		</dependency>
		<dependency>
			<groupId>com.sun.jersey</groupId>
			<artifactId>jersey-grizzly2</artifactId>
			<version>1.19</version>
		</dependency>
	</dependencies>
	<build>
		<finalName>rsexampleresponse</finalName>
	</build>
</project>

2. Main Application

package com.vvirlan;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import com.vvirlan.exception.IllegalArgumentExceptionMapper;
import com.vvirlan.resources.ExceptionResource;
import com.vvirlan.resources.HelloResource;

@ApplicationPath("rest")
public class ApplicationMain extends Application {

	@Override
	public Set<Class<?>> getClasses() {
		Set<Class<?>> classes = new HashSet<Class<?>>();
		classes.add(ExceptionResource.class);
//Note that you need to add the exception mapper here, otherwise, it won't work
		classes.add(IllegalArgumentExceptionMapper.class);
		return classes;
	}
}

3. An example service

package com.vvirlan.resources;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;

@Path("e")
public class ExceptionResource {
//This is the default implementation	
	@GET
	@Path("nf")
	public Response getException () {
		throw new WebApplicationException(Response.Status.CONFLICT);
	}
	
//Throw the IllegalArgument and it will get mapped automatically to whatever you define in the mapper (next class)
	@GET
	@Path("il")
	public Response getIllegal() {
		throw new IllegalArgumentException();
	}
}

4. The Exception Mapping class. Here we’re mapping the IllegalArgumentException to a BAD_REQUEST

package com.vvirlan.exception;

import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

@Provider
public class IllegalArgumentExceptionMapper implements ExceptionMapper<IllegalArgumentException> {

	public Response toResponse(IllegalArgumentException arg0) {
		return Response.status(Status.BAD_REQUEST).build();
	}

}

[JAX-RS] Using CDI for dependency injection in JAX-RS

1. The resource class

package com.example.jaxrs;

import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
@Path("cdiexample")
@RequestScoped
public class StringResource {
	@Inject
	private MyService service;
	public StringResource() {
	}
	@Context
	private HttpHeaders httpHeaders;
	@PostConstruct
	private void postCons() {
	}
	@Produces(MediaType.TEXT_PLAIN)
	@GET
	public String get() {
		return service.getMessage();
	}
}

2. MyService interface

package com.example.jaxrs;
public interface MyService {
	public String getMessage();
}

3. MyServiceImpl

package com.example.jaxrs;
public class MyServiceImpl implements MyService{
	@Override
	public String getMessage() {
		return "THIS IS THE MESSAGE";
	}
}

4. web.xml (under /WEB-INF/)

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
		 http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	version="3.1">
	<servlet>
		<servlet-name>javax.ws.rs.core.Application</servlet-name>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>javax.ws.rs.core.Application</servlet-name>
		<url-pattern>/rest/*</url-pattern>
	</servlet-mapping>
</web-app>

5. beans.xml (under /WEB-INF/)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/
XMLSchema-instance" xsi:schemeLocation="http://java.sun.com/xml/ns/javaee http://
java.sun.com/xml/ns/javaee/beans_1_0.xsd">
<!-- This is empty on purpose. -->
</beans>

6. Deploy on glassfish! and access it: http://localhost:8080/TestCDI/rest/cdiexample (given that the project name is TestCDI).

[JAX-RS] 3 ways to get cookies

These are 3 ways to obtain cookies values in JAX-RS

package com.example;

import javax.ws.rs.CookieParam;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.HttpHeaders;

@Path("/k")
public class CookieResource {

	@GET
	public String get(@CookieParam("customerId") int custId) {
		return "Customer ID was " + custId;
	}

	@GET
	@Path("object")
	public String getAnother(@CookieParam("customerId") Cookie customerId) {
		if (customerId != null) {
			return customerId.getName();
		}
		return "no cookie named customerId";
	}

	@GET
	@Path("headers")
	public String getHeaders(@Context HttpHeaders headers) {
		StringBuilder sb = new StringBuilder();
		for (String name : headers.getCookies().keySet()) {
			sb.append(name + " ");
		}
		return sb.toString();
	}
}

[JAX-RS] Simplest possible web service (on Tomcat)

1. SimpleService

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

@ApplicationPath("math")
@Path("table")
public class SimpleService extends Application {
	@GET
	@Path("/hello")
	public String addp(String num) {
		return "hello";
	}
}

2. pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.vvirlan</groupId>
	<artifactId>certif</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>certif Maven Webapp</name>
	<url>http://maven.apache.org</url>

	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>


		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.0.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.glassfish.jersey.containers</groupId>
			<artifactId>jersey-container-servlet</artifactId>
			<version>2.21</version>
		</dependency>
		<!-- uncomment this to get JSON support <dependency> <groupId>org.glassfish.jersey.media</groupId> 
			<artifactId>jersey-media-moxy</artifactId> </dependency> -->


	</dependencies>
	<build>
		<finalName>certif</finalName>
	</build>

	<properties>
		<jersey.version>2.21</jersey.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>
</project>

3. Layout
pic2

[JAX-RS] 4 ways to implement a client for web services

1. URLConnection client

package com.vvirlan;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;

public class URLConnectionClient {

	public static void main(String[] args) throws IOException {
		URL restURL = new URL("http://localhost:8080/simple-service-webapp/resources/myresource/usernamepwdcontext");
		URLConnection connection = (URLConnection) restURL.openConnection();
		connection.setDoOutput(true);
		connection.connect();
		InputStreamReader ins = new InputStreamReader(connection.getInputStream());
		BufferedReader in = new BufferedReader(ins);
		String inputLine;
		while ((inputLine = in.readLine()) != null) {
			System.out.println(inputLine);
		}
		in.close();
	}
}

2. HttpConnection client

package com.vvirlan;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class HttpConnectionClient {

	public static void main(String[] args) throws IOException {
		URL restURL = new URL("http://localhost:8080/simple-service-webapp/resources/myresource/usernamepwdcontext");
		HttpURLConnection connection  = (HttpURLConnection) restURL.openConnection();
		connection.setRequestMethod("GET");
		connection.setReadTimeout(10000);
		connection.connect();
		InputStreamReader ins = new InputStreamReader(connection.getInputStream());
		BufferedReader in = new BufferedReader(ins);
		String inputLine;
		while ((inputLine = in.readLine())!=null) {
			System.out.println(inputLine);
		}
		
	}
}

3. URL stream client

package com.vvirlan;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;

public class URLOpenClient {

	public static void main(String[] args) throws IOException {
		URL restURL = new URL("http://localhost:8080/simple-service-webapp/resources/myresource/usernamepwdcontext");
		InputStreamReader ins = new InputStreamReader(restURL.openStream());
		BufferedReader in = new BufferedReader(ins);
		String inputLine;
		while ((inputLine = in.readLine()) != null) {
			System.out.println(inputLine);
		}
		in.close();

	}
}

4. Jersey client.

package com.vvirlan;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Invocation.Builder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;

public class URLJerseyClient {

	public static void main(String[] args) {
		Client cl = ClientBuilder.newClient();
		WebTarget target = cl.target("http://localhost:8080/simple-service-webapp/resources/myresource/usernamepwdcontext");
		target.path("resource");
		Builder requestBuilder = target.request();
		Response response = requestBuilder.get();
		System.out.println(response.getStatus());
		System.out.println(response.readEntity(String.class));
	}
}

For this one you will need a dependency:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.vvirlan</groupId>
	<artifactId>cert</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>Client</name>

	<dependencies>
		<dependency>
			<groupId>org.glassfish.jersey.core</groupId>
			<artifactId>jersey-client</artifactId>
			<version>2.21</version>
		</dependency>
	</dependencies>
</project>