BAEL-3091: The Prototype Pattern in Java (changed code based on valid comments from a reader)

This commit is contained in:
Vivek Balasubramaniam
2019-10-29 22:27:15 +05:30
parent db85c8f275
commit d3d5b060e7
20517 changed files with 1642290 additions and 0 deletions
+13
View File
@@ -0,0 +1,13 @@
## Jersey
This module contains articles about Jersey.
### Relevant Articles
- [Jersey Filters and Interceptors](https://www.baeldung.com/jersey-filters-interceptors)
- [Jersey MVC Support](https://www.baeldung.com/jersey-mvc)
- [Bean Validation in Jersey](https://www.baeldung.com/jersey-bean-validation)
- [Set a Response Body in JAX-RS](https://www.baeldung.com/jax-rs-response)
- [Exploring the Jersey Test Framework](https://www.baeldung.com/jersey-test)
- [Explore Jersey Request Parameters](https://www.baeldung.com/jersey-request-parameters)
- [Add a Header to a Jersey SSE Client Request](https://www.baeldung.com/jersey-sse-client-request-headers)
+100
View File
@@ -0,0 +1,100 @@
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<artifactId>jersey</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>jersey</name>
<packaging>war</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.bundles</groupId>
<artifactId>jaxrs-ri</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-mvc-freemarker</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-bean-validation</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.security</groupId>
<artifactId>oauth1-client</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.security</groupId>
<artifactId>oauth2-client</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-sse</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework</groupId>
<artifactId>jersey-test-framework-core</artifactId>
<version>${jersey.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>${jersey.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>jersey</finalName>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>${maven-war-plugin.version}</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<configuration>
<mainClass>com.baeldung.jersey.server.http.EmbeddedHttpServer</mainClass>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<jersey.version>2.26</jersey.version>
</properties>
</project>
@@ -0,0 +1,45 @@
package com.baeldung.jersey.client;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.client.ClientConfig;
import com.baeldung.jersey.client.filter.RequestClientFilter;
import com.baeldung.jersey.client.filter.ResponseClientFilter;
import com.baeldung.jersey.client.interceptor.RequestClientWriterInterceptor;
public class JerseyClient {
private static final String URI_GREETINGS = "http://localhost:8080/jersey/greetings";
public static String getHelloGreeting() {
return createClient().target(URI_GREETINGS)
.request()
.get(String.class);
}
public static String getHiGreeting() {
return createClient().target(URI_GREETINGS + "/hi")
.request()
.get(String.class);
}
public static Response getCustomGreeting() {
return createClient().target(URI_GREETINGS + "/custom")
.request()
.post(Entity.text("custom"));
}
private static Client createClient() {
ClientConfig config = new ClientConfig();
config.register(RequestClientFilter.class);
config.register(ResponseClientFilter.class);
config.register(RequestClientWriterInterceptor.class);
return ClientBuilder.newClient(config);
}
}
@@ -0,0 +1,189 @@
package com.baeldung.jersey.client;
import com.baeldung.jersey.client.filter.AddHeaderOnRequestFilter;
import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
import org.glassfish.jersey.client.oauth1.AccessToken;
import org.glassfish.jersey.client.oauth1.ConsumerCredentials;
import org.glassfish.jersey.client.oauth1.OAuth1ClientSupport;
import org.glassfish.jersey.client.oauth2.OAuth2ClientSupport;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Feature;
import javax.ws.rs.core.Response;
import javax.ws.rs.sse.InboundSseEvent;
import javax.ws.rs.sse.SseEventSource;
import static org.glassfish.jersey.client.authentication.HttpAuthenticationFeature.*;
public class JerseyClientHeaders {
private static final String BEARER_CONSUMER_SECRET = "my-consumer-secret";
private static final String BEARER_ACCESS_TOKEN_SECRET = "my-access-token-secret";
private static final String TARGET = "http://localhost:9998/";
private static final String MAIN_RESOURCE = "echo-headers";
private static final String RESOURCE_AUTH_DIGEST = "digest";
private static String sseHeaderValue;
public static Response simpleHeader(String headerKey, String headerValue) {
Client client = ClientBuilder.newClient();
WebTarget webTarget = client.target(TARGET);
WebTarget resourceWebTarget = webTarget.path(MAIN_RESOURCE);
Invocation.Builder invocationBuilder = resourceWebTarget.request();
invocationBuilder.header(headerKey, headerValue);
return invocationBuilder.get();
}
public static Response simpleHeaderFluently(String headerKey, String headerValue) {
Client client = ClientBuilder.newClient();
return client.target(TARGET)
.path(MAIN_RESOURCE)
.request()
.header(headerKey, headerValue)
.get();
}
public static Response basicAuthenticationAtClientLevel(String username, String password) {
//To simplify we removed de SSL/TLS protection, but it's required to have an encryption
// when using basic authentication schema as it's send only on Base64 encoding
HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic(username, password);
Client client = ClientBuilder.newBuilder().register(feature).build();
return client.target(TARGET)
.path(MAIN_RESOURCE)
.request()
.get();
}
public static Response basicAuthenticationAtRequestLevel(String username, String password) {
//To simplify we removed de SSL/TLS protection, but it's required to have an encryption
// when using basic authentication schema as it's send only on Base64 encoding
HttpAuthenticationFeature feature = HttpAuthenticationFeature.basicBuilder().build();
Client client = ClientBuilder.newBuilder().register(feature).build();
return client.target(TARGET)
.path(MAIN_RESOURCE)
.request()
.property(HTTP_AUTHENTICATION_BASIC_USERNAME, username)
.property(HTTP_AUTHENTICATION_BASIC_PASSWORD, password)
.get();
}
public static Response digestAuthenticationAtClientLevel(String username, String password) {
HttpAuthenticationFeature feature = HttpAuthenticationFeature.digest(username, password);
Client client = ClientBuilder.newBuilder().register(feature).build();
return client.target(TARGET)
.path(MAIN_RESOURCE)
.path(RESOURCE_AUTH_DIGEST)
.request()
.get();
}
public static Response digestAuthenticationAtRequestLevel(String username, String password) {
HttpAuthenticationFeature feature = HttpAuthenticationFeature.digest();
Client client = ClientBuilder.newBuilder().register(feature).build();
return client.target(TARGET)
.path(MAIN_RESOURCE)
.path(RESOURCE_AUTH_DIGEST)
.request()
.property(HTTP_AUTHENTICATION_DIGEST_USERNAME, username)
.property(HTTP_AUTHENTICATION_DIGEST_PASSWORD, password)
.get();
}
public static Response bearerAuthenticationWithOAuth1AtClientLevel(String token, String consumerKey) {
ConsumerCredentials consumerCredential = new ConsumerCredentials(consumerKey, BEARER_CONSUMER_SECRET);
AccessToken accessToken = new AccessToken(token, BEARER_ACCESS_TOKEN_SECRET);
Feature feature = OAuth1ClientSupport
.builder(consumerCredential)
.feature()
.accessToken(accessToken)
.build();
Client client = ClientBuilder.newBuilder().register(feature).build();
return client.target(TARGET)
.path(MAIN_RESOURCE)
.request()
.get();
}
public static Response bearerAuthenticationWithOAuth1AtRequestLevel(String token, String consumerKey) {
ConsumerCredentials consumerCredential = new ConsumerCredentials(consumerKey, BEARER_CONSUMER_SECRET);
AccessToken accessToken = new AccessToken(token, BEARER_ACCESS_TOKEN_SECRET);
Feature feature = OAuth1ClientSupport
.builder(consumerCredential)
.feature()
.build();
Client client = ClientBuilder.newBuilder().register(feature).build();
return client.target(TARGET)
.path(MAIN_RESOURCE)
.request()
.property(OAuth1ClientSupport.OAUTH_PROPERTY_ACCESS_TOKEN, accessToken)
.get();
}
public static Response bearerAuthenticationWithOAuth2AtClientLevel(String token) {
Feature feature = OAuth2ClientSupport.feature(token);
Client client = ClientBuilder.newBuilder().register(feature).build();
return client.target(TARGET)
.path(MAIN_RESOURCE)
.request()
.get();
}
public static Response bearerAuthenticationWithOAuth2AtRequestLevel(String token, String otherToken) {
Feature feature = OAuth2ClientSupport.feature(token);
Client client = ClientBuilder.newBuilder().register(feature).build();
return client.target(TARGET)
.path(MAIN_RESOURCE)
.request()
.property(OAuth2ClientSupport.OAUTH2_PROPERTY_ACCESS_TOKEN, otherToken)
.get();
}
public static Response filter() {
Client client = ClientBuilder.newBuilder().register(AddHeaderOnRequestFilter.class).build();
return client.target(TARGET)
.path(MAIN_RESOURCE)
.request()
.get();
}
public static Response sendRestrictedHeaderThroughDefaultTransportConnector(String headerKey, String headerValue) {
Client client = ClientBuilder.newClient();
System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
return client.target(TARGET)
.path(MAIN_RESOURCE)
.request()
.header(headerKey, headerValue)
.get();
}
public static String simpleSSEHeader() throws InterruptedException {
Client client = ClientBuilder.newBuilder()
.register(AddHeaderOnRequestFilter.class)
.build();
WebTarget webTarget = client.target(TARGET)
.path(MAIN_RESOURCE)
.path("events");
SseEventSource sseEventSource = SseEventSource.target(webTarget).build();
sseEventSource.register(JerseyClientHeaders::receiveEvent);
sseEventSource.open();
Thread.sleep(3_000);
sseEventSource.close();
return sseHeaderValue;
}
private static void receiveEvent(InboundSseEvent event) {
sseHeaderValue = event.readData();
}
}
@@ -0,0 +1,16 @@
package com.baeldung.jersey.client.filter;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter;
import java.io.IOException;
public class AddHeaderOnRequestFilter implements ClientRequestFilter {
public static final String FILTER_HEADER_VALUE = "filter-header-value";
public static final String FILTER_HEADER_KEY = "x-filter-header";
@Override
public void filter(ClientRequestContext requestContext) throws IOException {
requestContext.getHeaders().add(FILTER_HEADER_KEY, FILTER_HEADER_VALUE);
}
}
@@ -0,0 +1,24 @@
package com.baeldung.jersey.client.filter;
import java.io.IOException;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.ext.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Provider
public class RequestClientFilter implements ClientRequestFilter {
private static final Logger LOG = LoggerFactory.getLogger(RequestClientFilter.class);
@Override
public void filter(ClientRequestContext requestContext) throws IOException {
LOG.info("Request client filter");
requestContext.setProperty("test", "test client request filter");
}
}
@@ -0,0 +1,26 @@
package com.baeldung.jersey.client.filter;
import java.io.IOException;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientResponseContext;
import javax.ws.rs.client.ClientResponseFilter;
import javax.ws.rs.ext.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Provider
public class ResponseClientFilter implements ClientResponseFilter {
private static final Logger LOG = LoggerFactory.getLogger(ResponseClientFilter.class);
@Override
public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
LOG.info("Response client filter");
responseContext.getHeaders()
.add("X-Test-Client", "Test response client filter");
}
}
@@ -0,0 +1,28 @@
package com.baeldung.jersey.client.interceptor;
import java.io.IOException;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.WriterInterceptor;
import javax.ws.rs.ext.WriterInterceptorContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Provider
public class RequestClientWriterInterceptor implements WriterInterceptor {
private static final Logger LOG = LoggerFactory.getLogger(RequestClientWriterInterceptor.class);
@Override
public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
LOG.info("request writer interceptor in the client side");
context.getOutputStream()
.write(("Message added in the writer interceptor in the client side").getBytes());
context.proceed();
}
}
@@ -0,0 +1,72 @@
package com.baeldung.jersey.server;
import com.baeldung.jersey.client.filter.AddHeaderOnRequestFilter;
import javax.annotation.security.RolesAllowed;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.*;
import javax.ws.rs.sse.OutboundSseEvent;
import javax.ws.rs.sse.Sse;
import javax.ws.rs.sse.SseEventSink;
@Path("/echo-headers")
public class EchoHeaders {
static final String REALM_KEY = "realm";
static final String REALM_VALUE = "Baeldung";
static final String QOP_KEY = "qop";
static final String QOP_VALUE = "auth";
static final String NONCE_KEY = "nonce";
static final String NONCE_VALUE = "dcd98b7102dd2f0e8b11d0f600bfb0c093";
static final String OPAQUE_KEY = "opaque";
static final String OPAQUE_VALUE = "5ccc069c403ebaf9f0171e9517f40e41";
static final String SSE_HEADER_KEY = "x-sse-header-key";
@Context
HttpHeaders headers;
@GET
public Response getHeadersBack() {
return echoHeaders();
}
@RolesAllowed("ADMIN")
@GET
@Path("/digest")
public Response getHeadersBackFromDigestAuthentication() {
// As the Digest authentication require some complex steps to work we'll simulate the process
// https://en.wikipedia.org/wiki/Digest_access_authentication#Example_with_explanation
if (headers.getHeaderString("authorization") == null) {
String authenticationRequired = "Digest " + REALM_KEY + "=\"" + REALM_VALUE + "\", " + QOP_KEY + "=\"" + QOP_VALUE + "\", " + NONCE_KEY + "=\"" + NONCE_VALUE + "\", " + OPAQUE_KEY + "=\"" + OPAQUE_VALUE + "\"";
return Response.status(Response.Status.UNAUTHORIZED)
.header("WWW-Authenticate", authenticationRequired)
.build();
} else {
return echoHeaders();
}
}
@GET
@Path("/events")
@Produces(MediaType.SERVER_SENT_EVENTS)
public void getServerSentEvents(@Context SseEventSink eventSink, @Context Sse sse) {
OutboundSseEvent event = sse.newEventBuilder()
.name("echo-headers")
.data(String.class, headers.getHeaderString(AddHeaderOnRequestFilter.FILTER_HEADER_KEY))
.build();
eventSink.send(event);
}
private Response echoHeaders() {
Response.ResponseBuilder responseBuilder = Response.noContent();
headers.getRequestHeaders()
.forEach((k, v) -> {
v.forEach(value -> responseBuilder.header(k, value));
});
return responseBuilder.build();
}
}
@@ -0,0 +1,32 @@
package com.baeldung.jersey.server;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import com.baeldung.jersey.server.config.HelloBinding;
@Path("/greetings")
public class Greetings {
@GET
@HelloBinding
public String getHelloGreeting() {
return "hello";
}
@GET
@Path("/hi")
public String getHiGreeting() {
return "hi";
}
@POST
@Path("/custom")
public Response getCustomGreeting(String name) {
return Response.status(Status.OK.getStatusCode())
.build();
}
}
@@ -0,0 +1,46 @@
package com.baeldung.jersey.server;
import javax.ws.rs.FormParam;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.PathParam;
public class ItemParam {
@HeaderParam("headerParam")
private String shopKey;
@PathParam("pathParam")
private String itemId;
@FormParam("formParam")
private String price;
public String getShopKey() {
return shopKey;
}
public void setShopKey(String shopKey) {
this.shopKey = shopKey;
}
public String getItemId() {
return itemId;
}
public void setItemId(String itemId) {
this.itemId = itemId;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
@Override
public String toString() {
return "ItemParam{shopKey='" + shopKey + ", itemId='" + itemId + ", price='" + price + '}';
}
}
@@ -0,0 +1,49 @@
package com.baeldung.jersey.server;
import javax.ws.rs.*;
@Path("items")
public class Items {
@GET
@Path("/cookie")
public String readCookieParam(@CookieParam("cookieParamToRead") String cookieParamToRead) {
return "Cookie parameter value is [" + cookieParamToRead + "]";
}
@GET
@Path("/header")
public String readHeaderParam(@HeaderParam("headerParamToRead") String headerParamToRead) {
return "Header parameter value is [" + headerParamToRead + "]";
}
@GET
@Path("/path/{pathParamToRead}")
public String readPathParam(@PathParam("pathParamToRead") String pathParamToRead) {
return "Path parameter value is [" + pathParamToRead + "]";
}
@GET
@Path("/query")
public String readQueryParam(@QueryParam("queryParamToRead") String queryParamToRead) {
return "Query parameter value is [" + queryParamToRead + "]";
}
@POST
@Path("/form")
public String readFormParam(@FormParam("formParamToRead") String formParamToRead) {
return "Form parameter value is [" + formParamToRead + "]";
}
@GET
@Path("/matrix")
public String readMatrixParam(@MatrixParam("matrixParamToRead") String matrixParamToRead) {
return "Matrix parameter value is [" + matrixParamToRead + "]";
}
@POST
@Path("/bean/{pathParam}")
public String readBeanParam(@BeanParam ItemParam itemParam) {
return itemParam.toString();
}
}
@@ -0,0 +1,102 @@
package com.baeldung.jersey.server;
import com.baeldung.jersey.server.model.Person;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@Path("/response")
public class Responder {
@GET
@Path("/ok")
public Response getOkResponse() {
String message = "This is a text response";
return Response
.status(Response.Status.OK)
.entity(message)
.build();
}
@GET
@Path("/not_ok")
public Response getNOkTextResponse() {
String message = "There was an internal server error";
return Response
.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(message)
.build();
}
@GET
@Path("/text_plain")
public Response getTextResponseTypeDefined() {
String message = "This is a plain text response";
return Response
.status(Response.Status.OK)
.entity(message)
.type(MediaType.TEXT_PLAIN)
.build();
}
@GET
@Path("/text_plain_annotation")
@Produces({ MediaType.TEXT_PLAIN })
public Response getTextResponseTypeAnnotated() {
String message = "This is a plain text response via annotation";
return Response
.status(Response.Status.OK)
.entity(message)
.build();
}
@GET
@Path("/pojo")
public Response getPojoResponse() {
Person person = new Person("Abh", "Nepal");
return Response
.status(Response.Status.OK)
.entity(person)
.build();
}
@GET
@Path("/json")
public Response getJsonResponse() {
String message = "{\"hello\": \"This is a JSON response\"}";
return Response
.status(Response.Status.OK)
.entity(message)
.type(MediaType.APPLICATION_JSON)
.build();
}
@GET
@Path("/xml")
@Produces(MediaType.TEXT_XML)
public String sayXMLHello() {
return "<?xml version=\"1.0\"?>" + "<hello> This is a xml response </hello>";
}
@GET
@Path("/html")
@Produces(MediaType.TEXT_HTML)
public String sayHtmlHello() {
return "<html> " + "<title>" + " This is a html title </title>" + "<body><h1>" + " This is a html response body " + "</body></h1>" + "</html> ";
}
}
@@ -0,0 +1,11 @@
package com.baeldung.jersey.server.config;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.ws.rs.NameBinding;
@NameBinding
@Retention(RetentionPolicy.RUNTIME)
public @interface HelloBinding {
}
@@ -0,0 +1,31 @@
package com.baeldung.jersey.server.config;
import javax.ws.rs.container.DynamicFeature;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.ext.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.baeldung.jersey.server.Greetings;
import com.baeldung.jersey.server.filter.ResponseServerFilter;
@Provider
public class HelloDynamicBinding implements DynamicFeature {
private static final Logger LOG = LoggerFactory.getLogger(HelloDynamicBinding.class);
@Override
public void configure(ResourceInfo resourceInfo, FeatureContext context) {
LOG.info("Hello dynamic binding");
if (Greetings.class.equals(resourceInfo.getResourceClass()) && resourceInfo.getResourceMethod()
.getName()
.contains("HiGreeting")) {
context.register(ResponseServerFilter.class);
}
}
}
@@ -0,0 +1,14 @@
package com.baeldung.jersey.server.config;
import javax.ws.rs.ApplicationPath;
import org.glassfish.jersey.server.ResourceConfig;
@ApplicationPath("/*")
public class ServerConfig extends ResourceConfig {
public ServerConfig() {
packages("com.baeldung.jersey.server");
}
}
@@ -0,0 +1,16 @@
package com.baeldung.jersey.server.config;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;
import org.glassfish.jersey.server.mvc.freemarker.FreemarkerMvcFeature;
public class ViewApplicationConfig extends ResourceConfig {
public ViewApplicationConfig() {
packages("com.baeldung.jersey.server");
property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
property(FreemarkerMvcFeature.TEMPLATE_BASE_PATH, "templates/freemarker");
register(FreemarkerMvcFeature.class);;
}
}
@@ -0,0 +1,35 @@
package com.baeldung.jersey.server.constraints;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.regex.Pattern;
import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = { SerialNumber.Validator.class })
public @interface SerialNumber {
String message()
default "Fruit serial number is not valid";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
public class Validator implements ConstraintValidator<SerialNumber, String> {
@Override
public void initialize(final SerialNumber serial) {
}
@Override
public boolean isValid(final String serial, final ConstraintValidatorContext constraintValidatorContext) {
final String serialNumRegex = "^\\d{3}-\\d{3}-\\d{4}$";
return Pattern.matches(serialNumRegex, serial);
}
}
}
@@ -0,0 +1,27 @@
package com.baeldung.jersey.server.filter;
import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.ext.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Provider
@PreMatching
public class PrematchingRequestFilter implements ContainerRequestFilter {
private static final Logger LOG = LoggerFactory.getLogger(PrematchingRequestFilter.class);
@Override
public void filter(ContainerRequestContext ctx) throws IOException {
LOG.info("prematching filter");
if (ctx.getMethod()
.equals("DELETE")) {
LOG.info("\"Deleting request");
}
}
}
@@ -0,0 +1,23 @@
package com.baeldung.jersey.server.filter;
import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ResponseServerFilter implements ContainerResponseFilter {
private static final Logger LOG = LoggerFactory.getLogger(ResponseServerFilter.class);
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
LOG.info("Response server filter");
responseContext.getHeaders()
.add("X-Test", "Filter test");
}
}
@@ -0,0 +1,36 @@
package com.baeldung.jersey.server.filter;
import java.io.IOException;
import javax.annotation.Priority;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.baeldung.jersey.server.config.HelloBinding;
@Provider
@Priority(Priorities.AUTHORIZATION)
@HelloBinding
public class RestrictedOperationsRequestFilter implements ContainerRequestFilter {
private static final Logger LOG = LoggerFactory.getLogger(RestrictedOperationsRequestFilter.class);
@Override
public void filter(ContainerRequestContext ctx) throws IOException {
LOG.info("Restricted operations filter");
if (ctx.getLanguage() != null && "EN".equals(ctx.getLanguage()
.getLanguage())) {
LOG.info("Aborting request");
ctx.abortWith(Response.status(Response.Status.FORBIDDEN)
.entity("Cannot access")
.build());
}
}
}
@@ -0,0 +1,41 @@
package com.baeldung.jersey.server.http;
import java.io.IOException;
import java.net.URI;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
import com.baeldung.jersey.server.config.ViewApplicationConfig;
public class EmbeddedHttpServer {
public static final URI BASE_URI = URI.create("http://localhost:8082/");
public static void main(String[] args) {
try {
final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(BASE_URI, new ViewApplicationConfig(), false);
Runtime.getRuntime()
.addShutdownHook(new Thread(() -> {
server.shutdownNow();
}));
server.start();
System.out.println(String.format("Application started.\nTry out %s\nStop the application using CTRL+C", BASE_URI + "fruit"));
} catch (IOException ex) {
Logger.getLogger(EmbeddedHttpServer.class.getName())
.log(Level.SEVERE, null, ex);
}
}
public static HttpServer startServer() {
final ResourceConfig rc = new ResourceConfig().packages("com.baeldung.jersey.server");
return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI.toString()), rc);
}
}
@@ -0,0 +1,36 @@
package com.baeldung.jersey.server.interceptor;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.stream.Collectors;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.ReaderInterceptor;
import javax.ws.rs.ext.ReaderInterceptorContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Provider
public class RequestServerReaderInterceptor implements ReaderInterceptor {
private static final Logger LOG = LoggerFactory.getLogger(RequestServerReaderInterceptor.class);
@Override
public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
LOG.info("Request reader interceptor in the server side");
InputStream is = context.getInputStream();
String body = new BufferedReader(new InputStreamReader(is)).lines()
.collect(Collectors.joining("\n"));
context.setInputStream(new ByteArrayInputStream((body + " message added in server reader interceptor").getBytes()));
return context.proceed();
}
}
@@ -0,0 +1,62 @@
package com.baeldung.jersey.server.model;
import javax.validation.constraints.Min;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Fruit {
@Min(value = 10, message = "Fruit weight must be 10 or greater")
private Integer weight;
@Size(min = 5, max = 200)
private String name;
@Size(min = 5, max = 200)
private String colour;
private String serial;
public Fruit() {
}
public Fruit(String name, String colour) {
this.name = name;
this.colour = colour;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setColour(String colour) {
this.colour = colour;
}
public String getColour() {
return colour;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
public String getSerial() {
return serial;
}
public void setSerial(String serial) {
this.serial = serial;
}
@Override
public String toString() {
return "Fruit [name: " + getName() + " colour: " + getColour() + "]";
}
}
@@ -0,0 +1,32 @@
package com.baeldung.jersey.server.model;
public class Person {
String name;
String address;
public Person(String name, String address) {
this.name = name;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Person [name: " + getName() + " address: " + getAddress() + "]";
}
}
@@ -0,0 +1,26 @@
package com.baeldung.jersey.server.providers;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
public class FruitExceptionMapper implements ExceptionMapper<ConstraintViolationException> {
@Override
public Response toResponse(final ConstraintViolationException exception) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(prepareMessage(exception))
.type("text/plain")
.build();
}
private String prepareMessage(ConstraintViolationException exception) {
final StringBuilder message = new StringBuilder();
for (ConstraintViolation<?> cv : exception.getConstraintViolations()) {
message.append(cv.getPropertyPath() + " " + cv.getMessage() + "\n");
}
return message.toString();
}
}
@@ -0,0 +1,120 @@
package com.baeldung.jersey.server.rest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
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.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.glassfish.jersey.server.mvc.ErrorTemplate;
import org.glassfish.jersey.server.mvc.Template;
import org.glassfish.jersey.server.mvc.Viewable;
import com.baeldung.jersey.server.constraints.SerialNumber;
import com.baeldung.jersey.server.model.Fruit;
import com.baeldung.jersey.service.SimpleStorageService;
@Path("/fruit")
public class FruitResource {
@GET
public Viewable get() {
return new Viewable("/index.ftl", "Fruit Index Page");
}
@GET
@Template(name = "/all.ftl")
@Path("/all")
@Produces(MediaType.TEXT_HTML)
public Map<String, Object> getAllFruit() {
final List<Fruit> fruits = new ArrayList<>();
fruits.add(new Fruit("banana", "yellow"));
fruits.add(new Fruit("apple", "red"));
fruits.add(new Fruit("kiwi", "green"));
final Map<String, Object> model = new HashMap<String, Object>();
model.put("items", fruits);
return model;
}
@GET
@ErrorTemplate(name = "/error.ftl")
@Template(name = "/named.ftl")
@Path("{name}")
@Produces(MediaType.TEXT_HTML)
public String getFruitByName(@PathParam("name") String name) {
if (!"banana".equalsIgnoreCase(name)) {
throw new IllegalArgumentException("Fruit not found: " + name);
}
return name;
}
@POST
@Path("/create")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void createFruit(
@NotNull(message = "Fruit name must not be null") @FormParam("name") String name,
@NotNull(message = "Fruit colour must not be null") @FormParam("colour") String colour) {
Fruit fruit = new Fruit(name, colour);
SimpleStorageService.storeFruit(fruit);
}
@PUT
@Path("/update")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void updateFruit(@SerialNumber @FormParam("serial") String serial) {
Fruit fruit = new Fruit();
fruit.setSerial(serial);
SimpleStorageService.storeFruit(fruit);
}
@POST
@Path("/create")
@Consumes(MediaType.APPLICATION_JSON)
public void createFruit(@Valid Fruit fruit) {
SimpleStorageService.storeFruit(fruit);
}
@POST
@Path("/created")
@Consumes(MediaType.APPLICATION_JSON)
public Response createNewFruit(@Valid Fruit fruit) {
String result = "Fruit saved : " + fruit;
return Response.status(Status.CREATED.getStatusCode())
.entity(result)
.build();
}
@GET
@Valid
@Produces(MediaType.APPLICATION_JSON)
@Path("/search/{name}")
public Fruit findFruitByName(@PathParam("name") String name) {
return SimpleStorageService.findByName(name);
}
@GET
@Produces(MediaType.TEXT_HTML)
@Path("/exception")
@Valid
public Fruit exception() {
Fruit fruit = new Fruit();
fruit.setName("a");
fruit.setColour("b");
return fruit;
}
}
@@ -0,0 +1,25 @@
package com.baeldung.jersey.service;
import java.util.HashMap;
import java.util.Map;
import com.baeldung.jersey.server.model.Fruit;
public class SimpleStorageService {
private static final Map<String, Fruit> fruits = new HashMap<String, Fruit>();
public static void storeFruit(final Fruit fruit) {
fruits.put(fruit.getName(), fruit);
}
public static Fruit findByName(final String name) {
return fruits.entrySet()
.stream()
.filter(map -> name.equals(map.getKey()))
.map(map -> map.getValue())
.findFirst()
.get();
}
}
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>
@@ -0,0 +1,14 @@
<html>
<head>
<title>All fruit!</title>
</head>
<body>
<h1>All fruit!</h1>
<p>Fruits:</p>
<ul>
<#list items as fruit>
<li>${fruit.name}</li>
</#list>
</ul>
</body>
</html>
@@ -0,0 +1,8 @@
<html>
<head>
<title>Welcome!</title>
</head>
<body>
<h1>Error - ${model.message}!</h1>
</body>
</html>
@@ -0,0 +1,8 @@
<html>
<head>
<title>Welcome!</title>
</head>
<body>
<h1>Welcome ${model}!</h1>
</body>
</html>
@@ -0,0 +1,8 @@
<html>
<head>
<title>Welcome!</title>
</head>
<body>
<h1>Found fruit - ${model}!</h1>
</body>
</html>
@@ -0,0 +1,35 @@
package com.baeldung.jersey.client;
import javax.ws.rs.core.Response;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
@Ignore
public class JerseyClientIntegrationTest {
private static int HTTP_OK = 200;
@Test
public void givenGreetingResource_whenCallingHelloGreeting_thenHelloReturned() {
String response = JerseyClient.getHelloGreeting();
Assert.assertEquals("hello", response);
}
@Test
public void givenGreetingResource_whenCallingHiGreeting_thenHiReturned() {
String response = JerseyClient.getHiGreeting();
Assert.assertEquals("hi", response);
}
@Test
public void givenGreetingResource_whenCallingCustomGreeting_thenCustomGreetingReturned() {
Response response = JerseyClient.getCustomGreeting();
Assert.assertEquals(HTTP_OK, response.getStatus());
}
}
@@ -0,0 +1,197 @@
package com.baeldung.jersey.server;
import com.baeldung.jersey.client.JerseyClientHeaders;
import com.baeldung.jersey.client.filter.AddHeaderOnRequestFilter;
import org.glassfish.jersey.media.sse.SseFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Response;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
public class EchoHeadersUnitTest extends JerseyTest {
private static final String SIMPLE_HEADER_KEY = "my-header-key";
private static final String SIMPLE_HEADER_VALUE = "my-header-value";
private static final String USERNAME = "baeldung";
private static final String PASSWORD = "super-secret";
private static final String AUTHORIZATION_HEADER_KEY = "authorization";
private static final String BEARER_TOKEN_VALUE = "my-token";
private static final String BEARER_CONSUMER_KEY_VALUE = "my-consumer-key";
private static final String BEARER_REQUEST_TOKEN_VALUE = "my-request-token";
@Test
public void whenCallingSimpleHeader_thenHeadersReturnedBack() {
Response response = JerseyClientHeaders.simpleHeader(SIMPLE_HEADER_KEY, SIMPLE_HEADER_VALUE);
assertEquals(response.getHeaderString(SIMPLE_HEADER_KEY), SIMPLE_HEADER_VALUE);
}
@Test
public void whenCallingSimpleHeaderFluently_thenHeadersReturnedBack() {
Response response = JerseyClientHeaders.simpleHeaderFluently(SIMPLE_HEADER_KEY, SIMPLE_HEADER_VALUE);
assertEquals(response.getHeaderString(SIMPLE_HEADER_KEY), SIMPLE_HEADER_VALUE);
}
@Test
public void whenCallingBasicAuthenticationAtClientLevel_thenHeadersReturnedBack() {
Response response = JerseyClientHeaders.basicAuthenticationAtClientLevel(USERNAME, PASSWORD);
assertBasicAuthenticationHeaders(response);
}
@Test
public void whenCallingBasicAuthenticationAtRequestLevel_thenHeadersReturnedBack() {
Response response = JerseyClientHeaders.basicAuthenticationAtRequestLevel(USERNAME, PASSWORD);
assertBasicAuthenticationHeaders(response);
}
@Test
public void whenCallingDigestAuthenticationAtClientLevel_thenHeadersReturnedBack() {
Response response = JerseyClientHeaders.digestAuthenticationAtClientLevel(USERNAME, PASSWORD);
Map<String, String> subHeadersMap = parseAuthenticationSubHeader(response, 7);
assertDigestAuthenticationHeaders(subHeadersMap);
}
@Test
public void whenCallingDigestAuthenticationAtRequestLevel_thenHeadersReturnedBack() {
Response response = JerseyClientHeaders.digestAuthenticationAtRequestLevel(USERNAME, PASSWORD);
Map<String, String> subHeadersMap = parseAuthenticationSubHeader(response, 7);
assertDigestAuthenticationHeaders(subHeadersMap);
}
@Test
public void whenCallingBearerAuthenticationWithOAuth1AtClientLevel_thenHeadersReturnedBack() {
Response response = JerseyClientHeaders.bearerAuthenticationWithOAuth1AtClientLevel(BEARER_TOKEN_VALUE, BEARER_CONSUMER_KEY_VALUE);
Map<String, String> subHeadersMap = parseAuthenticationSubHeader(response, 6);
assertBearerAuthenticationHeaders(subHeadersMap);
}
@Test
public void whenCallingBearerAuthenticationWithOAuth1AtRequestLevel_thenHeadersReturnedBack() {
Response response = JerseyClientHeaders.bearerAuthenticationWithOAuth1AtRequestLevel(BEARER_TOKEN_VALUE, BEARER_CONSUMER_KEY_VALUE);
Map<String, String> subHeadersMap = parseAuthenticationSubHeader(response, 6);
assertBearerAuthenticationHeaders(subHeadersMap);
}
@Test
public void whenCallingBearerAuthenticationWithOAuth2AtClientLevel_thenHeadersReturnedBack() {
Response response = JerseyClientHeaders.bearerAuthenticationWithOAuth2AtClientLevel(BEARER_TOKEN_VALUE);
assertEquals("Bearer " + BEARER_TOKEN_VALUE, response.getHeaderString(AUTHORIZATION_HEADER_KEY));
}
@Test
public void whenCallingBearerAuthenticationWithOAuth2AtRequestLevel_thenHeadersReturnedBack() {
Response response = JerseyClientHeaders.bearerAuthenticationWithOAuth2AtRequestLevel(BEARER_TOKEN_VALUE, BEARER_REQUEST_TOKEN_VALUE);
assertEquals("Bearer " + BEARER_REQUEST_TOKEN_VALUE, response.getHeaderString(AUTHORIZATION_HEADER_KEY));
}
@Test
public void whenCallingFilter_thenHeadersReturnedBack() {
Response response = JerseyClientHeaders.filter();
assertEquals(AddHeaderOnRequestFilter.FILTER_HEADER_VALUE, response.getHeaderString(AddHeaderOnRequestFilter.FILTER_HEADER_KEY));
}
@Test
public void whenCallingSendRestrictedHeaderThroughDefaultTransportConnector_thenHeadersReturnedBack() {
Response response = JerseyClientHeaders.sendRestrictedHeaderThroughDefaultTransportConnector("keep-alive", "keep-alive-value");
assertEquals("keep-alive-value", response.getHeaderString("keep-alive"));
}
@Test
public void whenCallingSimpleSSEHeader_thenHeadersReturnedBack() throws InterruptedException {
String sseHeaderBackValue = JerseyClientHeaders.simpleSSEHeader();
assertEquals(AddHeaderOnRequestFilter.FILTER_HEADER_VALUE, sseHeaderBackValue);
}
private void assertBearerAuthenticationHeaders(Map<String, String> subHeadersMap) {
assertEquals(BEARER_TOKEN_VALUE, subHeadersMap.get("oauth_token"));
assertEquals(BEARER_CONSUMER_KEY_VALUE, subHeadersMap.get("oauth_consumer_key"));
assertNotNull(subHeadersMap.get("oauth_nonce"));
assertNotNull(subHeadersMap.get("oauth_signature"));
assertNotNull(subHeadersMap.get("oauth_callback"));
assertNotNull(subHeadersMap.get("oauth_signature_method"));
assertNotNull(subHeadersMap.get("oauth_version"));
assertNotNull(subHeadersMap.get("oauth_timestamp"));
}
private void assertDigestAuthenticationHeaders(Map<String, String> subHeadersMap) {
assertEquals(EchoHeaders.NONCE_VALUE, subHeadersMap.get(EchoHeaders.NONCE_KEY));
assertEquals(EchoHeaders.OPAQUE_VALUE, subHeadersMap.get(EchoHeaders.OPAQUE_KEY));
assertEquals(EchoHeaders.QOP_VALUE, subHeadersMap.get(EchoHeaders.QOP_KEY));
assertEquals(EchoHeaders.REALM_VALUE, subHeadersMap.get(EchoHeaders.REALM_KEY));
assertEquals(USERNAME, subHeadersMap.get("username"));
assertEquals("/echo-headers/digest", subHeadersMap.get("uri"));
assertNotNull(subHeadersMap.get("cnonce"));
assertEquals("00000001", subHeadersMap.get("nc"));
assertNotNull(subHeadersMap.get("response"));
}
private Map<String, String> parseAuthenticationSubHeader(Response response, int startAt) {
String authorizationHeader = response.getHeaderString(AUTHORIZATION_HEADER_KEY);
// The substring(startAt) is used to cut off the authentication schema part from the value returned.
String[] subHeadersKeyValue = authorizationHeader.substring(startAt).split(",");
Map<String, String> subHeadersMap = new HashMap<>();
for (String subHeader : subHeadersKeyValue) {
String[] keyValue = subHeader.split("=");
if (keyValue[1].startsWith("\"")) {
keyValue[1] = keyValue[1].substring(1, keyValue[1].length() - 1);
}
subHeadersMap.put(keyValue[0].trim(), keyValue[1].trim());
}
return subHeadersMap;
}
private void assertBasicAuthenticationHeaders(Response response) {
String base64Credentials = response.getHeaderString(AUTHORIZATION_HEADER_KEY);
// The substring(6) is used to cut the "Basic " part of the value returned,
// as it's used to indicates the authentication schema and does not belong to the credentials
byte[] credentials = Base64.getDecoder().decode(base64Credentials.substring(6));
String[] credentialsParsed = new String(credentials).split(":");
assertEquals(credentialsParsed[0], USERNAME);
assertEquals(credentialsParsed[1], PASSWORD);
}
@Override
protected Application configure() {
return new ResourceConfig()
.register(EchoHeaders.class);
}
@Override
public void setUp() throws Exception {
super.setUp();
// We need this definition here, because if you are running
// the complete suit test the sendingRestrictedHeaderThroughDefaultTransportConnector_shouldReturnThanBack
// will fail if only defined on the client method, since the JerseyTest is created once.
System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
}
}
@@ -0,0 +1,33 @@
package com.baeldung.jersey.server;
import static org.junit.Assert.assertEquals;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
public class GreetingsResourceIntegrationTest extends JerseyTest {
@Override
protected Application configure() {
return new ResourceConfig(Greetings.class);
}
@Test
public void givenGetHiGreeting_whenCorrectRequest_thenResponseIsOkAndContainsHi() {
Response response = target("/greetings/hi").request()
.get();
assertEquals("Http Response should be 200: ", Status.OK.getStatusCode(), response.getStatus());
assertEquals("Http Content-Type should be: ", MediaType.TEXT_HTML, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
String content = response.readEntity(String.class);
assertEquals("Content of ressponse is: ", "hi", content);
}
}
@@ -0,0 +1,52 @@
package com.baeldung.jersey.server;
import static org.junit.Assert.assertEquals;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import org.glassfish.grizzly.http.server.HttpServer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.baeldung.jersey.server.http.EmbeddedHttpServer;
public class ItemsUnitTest {
private HttpServer server;
private WebTarget target;
@Before
public void setUp() throws Exception {
server = EmbeddedHttpServer.startServer();
target = ClientBuilder.newClient().target(EmbeddedHttpServer.BASE_URI.toString());
}
@After
public void tearDown() throws Exception {
server.stop();
}
@Test
public void givenCookieParameter_whenGet_thenReturnsExpectedText() {
String paramValue = "1";
String responseText = target.path("items/cookie").request().cookie("cookieParamToRead", paramValue).get(String.class);
assertEquals("Cookie parameter value is [" + paramValue + "]", responseText);
}
@Test
public void givenHeaderParameter_whenGet_thenReturnsExpectedText() {
String paramValue = "2";
String responseText = target.path("items/header").request().header("headerParamToRead", paramValue).get(String.class);
assertEquals("Header parameter value is [" + paramValue + "]", responseText);
}
@Test
public void givenPathParameter_whenGet_thenReturnsExpectedText() {
String paramValue = "3";
String responseText = target.path("items/path/" + paramValue).request().get(String.class);
assertEquals("Path parameter value is [" + paramValue + "]", responseText);
}
}
@@ -0,0 +1,145 @@
package com.baeldung.jersey.server.rest;
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.TestProperties;
import org.junit.Test;
import com.baeldung.jersey.server.config.ViewApplicationConfig;
import com.baeldung.jersey.server.model.Fruit;
import com.baeldung.jersey.server.providers.FruitExceptionMapper;
public class FruitResourceIntegrationTest extends JerseyTest {
@Override
protected Application configure() {
enable(TestProperties.LOG_TRAFFIC);
enable(TestProperties.DUMP_ENTITY);
forceSet(TestProperties.CONTAINER_PORT, "0");
ViewApplicationConfig config = new ViewApplicationConfig();
config.register(FruitExceptionMapper.class);
return config;
}
@Test
public void givenGetAllFruit_whenCorrectRequest_thenAllTemplateInvoked() {
final String response = target("/fruit/all").request()
.get(String.class);
assertThat(response, allOf(containsString("banana"), containsString("apple"), containsString("kiwi")));
}
@Test
public void givenGetFruit_whenCorrectRequest_thenIndexTemplateInvoked() {
final String response = target("/fruit").request()
.get(String.class);
assertThat(response, containsString("Welcome Fruit Index Page!"));
}
@Test
public void givenGetFruitByName_whenFruitUnknown_thenErrorTemplateInvoked() {
final String response = target("/fruit/orange").request()
.get(String.class);
assertThat(response, containsString("Error - Fruit not found: orange!"));
}
@Test
public void givenCreateFruit_whenFormContainsNullParam_thenResponseCodeIsBadRequest() {
Form form = new Form();
form.param("name", "apple");
form.param("colour", null);
Response response = target("fruit/create").request(MediaType.APPLICATION_FORM_URLENCODED)
.post(Entity.form(form));
assertEquals("Http Response should be 400 ", 400, response.getStatus());
assertThat(response.readEntity(String.class), containsString("Fruit colour must not be null"));
}
@Test
public void givenCreateFruit_whenJsonIsCorrect_thenResponseCodeIsCreated() {
Response response = target("fruit/created").request()
.post(Entity.json("{\"name\":\"strawberry\",\"weight\":20}"));
assertEquals("Http Response should be 201 ", Status.CREATED.getStatusCode(), response.getStatus());
assertThat(response.readEntity(String.class), containsString("Fruit saved : Fruit [name: strawberry colour: null]"));
}
@Test
public void givenUpdateFruit_whenFormContainsBadSerialParam_thenResponseCodeIsBadRequest() {
Form form = new Form();
form.param("serial", "2345-2345");
Response response = target("fruit/update").request(MediaType.APPLICATION_FORM_URLENCODED)
.put(Entity.form(form));
assertEquals("Http Response should be 400 ", 400, response.getStatus());
assertThat(response.readEntity(String.class), containsString("Fruit serial number is not valid"));
}
@Test
public void givenCreateFruit_whenFruitIsInvalid_thenResponseCodeIsBadRequest() {
Fruit fruit = new Fruit("Blueberry", "purple");
fruit.setWeight(1);
Response response = target("fruit/create").request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.entity(fruit, MediaType.APPLICATION_JSON_TYPE));
assertEquals("Http Response should be 400 ", 400, response.getStatus());
assertThat(response.readEntity(String.class), containsString("Fruit weight must be 10 or greater"));
}
@Test
public void givenFruitExists_whenSearching_thenResponseContainsFruit() {
Fruit fruit = new Fruit();
fruit.setName("strawberry");
fruit.setWeight(20);
Response response = target("fruit/create").request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.entity(fruit, MediaType.APPLICATION_JSON_TYPE));
assertEquals("Http Response should be 204 ", 204, response.getStatus());
final String json = target("fruit/search/strawberry").request()
.get(String.class);
assertThat(json, containsString("{\"name\":\"strawberry\",\"weight\":20}"));
}
@Test
public void givenFruitExists_whenSearching_thenResponseContainsFruitEntity() {
Fruit fruit = new Fruit();
fruit.setName("strawberry");
fruit.setWeight(20);
Response response = target("fruit/create").request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.entity(fruit, MediaType.APPLICATION_JSON_TYPE));
assertEquals("Http Response should be 204 ", 204, response.getStatus());
final Fruit entity = target("fruit/search/strawberry").request()
.get(Fruit.class);
assertEquals("Fruit name: ", "strawberry", entity.getName());
assertEquals("Fruit weight: ", Integer.valueOf(20), entity.getWeight());
}
@Test
public void givenFruit_whenFruitIsInvalid_thenReponseContainsCustomExceptions() {
final Response response = target("fruit/exception").request()
.get();
assertEquals("Http Response should be 400 ", 400, response.getStatus());
String responseString = response.readEntity(String.class);
assertThat(responseString, containsString("exception.<return value>.colour size must be between 5 and 200"));
assertThat(responseString, containsString("exception.<return value>.name size must be between 5 and 200"));
}
}