JAVA-29231 Move modules inside existing container modules (#15492)
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
package com.baeldung.jersey.client;
|
||||
|
||||
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;
|
||||
import com.baeldung.jersey.server.Greetings;
|
||||
|
||||
import jakarta.ws.rs.client.Client;
|
||||
import jakarta.ws.rs.client.ClientBuilder;
|
||||
import jakarta.ws.rs.client.Entity;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
public class JerseyClient {
|
||||
|
||||
public 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);
|
||||
config.register(Greetings.class);
|
||||
|
||||
return ClientBuilder.newClient(config);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
package com.baeldung.jersey.client;
|
||||
|
||||
import com.baeldung.jersey.client.filter.AddHeaderOnRequestFilter;
|
||||
import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
|
||||
import org.glassfish.jersey.client.ClientConfig;
|
||||
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 static org.glassfish.jersey.client.authentication.HttpAuthenticationFeature.*;
|
||||
|
||||
import jakarta.ws.rs.client.Client;
|
||||
import jakarta.ws.rs.client.ClientBuilder;
|
||||
import jakarta.ws.rs.client.Invocation;
|
||||
import jakarta.ws.rs.client.WebTarget;
|
||||
import jakarta.ws.rs.core.Feature;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.sse.InboundSseEvent;
|
||||
import jakarta.ws.rs.sse.SseEventSource;
|
||||
|
||||
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) {
|
||||
ClientConfig clientConfig = new ClientConfig().connectorProvider(new ApacheConnectorProvider());
|
||||
Client client = ClientBuilder.newClient(clientConfig);
|
||||
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();
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package com.baeldung.jersey.client.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import jakarta.ws.rs.client.ClientRequestContext;
|
||||
import jakarta.ws.rs.client.ClientRequestFilter;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.baeldung.jersey.client.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.ws.rs.client.ClientRequestContext;
|
||||
import jakarta.ws.rs.client.ClientRequestFilter;
|
||||
import jakarta.ws.rs.ext.Provider;
|
||||
|
||||
@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");
|
||||
}
|
||||
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.baeldung.jersey.client.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.ws.rs.client.ClientRequestContext;
|
||||
import jakarta.ws.rs.client.ClientResponseContext;
|
||||
import jakarta.ws.rs.client.ClientResponseFilter;
|
||||
import jakarta.ws.rs.ext.Provider;
|
||||
|
||||
@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");
|
||||
}
|
||||
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.baeldung.jersey.client.interceptor;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import jakarta.ws.rs.ext.Provider;
|
||||
import jakarta.ws.rs.ext.WriterInterceptor;
|
||||
import jakarta.ws.rs.ext.WriterInterceptorContext;
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.jersey.client.listdemo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
|
||||
@Path("/")
|
||||
public class JerseyListDemo {
|
||||
@GET
|
||||
public String getItems(@QueryParam("items") List<String> items) {
|
||||
return "Received items: " + items;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.baeldung.jersey.client.listdemo;
|
||||
|
||||
import org.glassfish.jersey.server.ResourceConfig;
|
||||
|
||||
public class ListDemoApp extends ResourceConfig {
|
||||
public ListDemoApp() {
|
||||
packages("com.baeldung.jersey.client.listdemo");
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.baeldung.jersey.exceptionhandling;
|
||||
|
||||
import org.glassfish.jersey.server.ResourceConfig;
|
||||
|
||||
import com.baeldung.jersey.exceptionhandling.rest.exceptions.IllegalArgumentExceptionMapper;
|
||||
import com.baeldung.jersey.exceptionhandling.rest.exceptions.ServerExceptionMapper;
|
||||
|
||||
import jakarta.ws.rs.ApplicationPath;
|
||||
|
||||
@ApplicationPath("/exception-handling/*")
|
||||
public class ExceptionHandlingConfig extends ResourceConfig {
|
||||
|
||||
public ExceptionHandlingConfig() {
|
||||
packages("com.baeldung.jersey.exceptionhandling.rest");
|
||||
register(IllegalArgumentExceptionMapper.class);
|
||||
register(ServerExceptionMapper.class);
|
||||
}
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package com.baeldung.jersey.exceptionhandling.data;
|
||||
|
||||
import com.baeldung.jersey.exceptionhandling.repo.Identifiable;
|
||||
|
||||
public class Stock implements Identifiable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String id;
|
||||
private Double price;
|
||||
|
||||
public Stock() {
|
||||
}
|
||||
|
||||
public Stock(String id, Double price) {
|
||||
this.id = id;
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Double getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public void setPrice(Double price) {
|
||||
this.price = price;
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
package com.baeldung.jersey.exceptionhandling.data;
|
||||
|
||||
import com.baeldung.jersey.exceptionhandling.repo.Identifiable;
|
||||
|
||||
public class Wallet implements Identifiable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static final Double MIN_CHARGE = 50.0;
|
||||
public static final String MIN_CHARGE_MSG = "minimum charge is: " + MIN_CHARGE;
|
||||
|
||||
private String id;
|
||||
private Double balance = 0.0;
|
||||
|
||||
public Wallet() {
|
||||
}
|
||||
|
||||
public Wallet(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Double getBalance() {
|
||||
return balance;
|
||||
}
|
||||
|
||||
public void setBalance(Double balance) {
|
||||
this.balance = balance;
|
||||
}
|
||||
|
||||
public Double addBalance(Double amount) {
|
||||
if (balance == null)
|
||||
balance = 0.0;
|
||||
|
||||
return balance += amount;
|
||||
}
|
||||
|
||||
public boolean hasFunds(Double amount) {
|
||||
if (balance == null || amount == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (balance - amount) >= 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.baeldung.jersey.exceptionhandling.repo;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Db<T extends Identifiable> {
|
||||
private Map<String, T> db = new HashMap<>();
|
||||
|
||||
public Optional<T> findById(String id) {
|
||||
return Optional.ofNullable(db.get(id));
|
||||
}
|
||||
|
||||
public String save(T t) {
|
||||
String id = t.getId();
|
||||
if (id == null) {
|
||||
id = UUID.randomUUID()
|
||||
.toString();
|
||||
t.setId(id);
|
||||
}
|
||||
db.put(id, t);
|
||||
return id;
|
||||
}
|
||||
|
||||
public void remove(T t) {
|
||||
db.entrySet()
|
||||
.removeIf(entry -> entry.getValue()
|
||||
.getId()
|
||||
.equals(t.getId()));
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package com.baeldung.jersey.exceptionhandling.repo;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public interface Identifiable extends Serializable {
|
||||
void setId(String id);
|
||||
|
||||
String getId();
|
||||
|
||||
public static void assertValid(Identifiable i) {
|
||||
if (i == null)
|
||||
throw new IllegalArgumentException("object cannot be null");
|
||||
|
||||
if (i.getId() == null)
|
||||
throw new IllegalArgumentException("object id cannot be null");
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package com.baeldung.jersey.exceptionhandling.rest;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.baeldung.jersey.exceptionhandling.data.Stock;
|
||||
import com.baeldung.jersey.exceptionhandling.repo.Db;
|
||||
import com.baeldung.jersey.exceptionhandling.service.Repository;
|
||||
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
@Path("/stocks")
|
||||
public class StocksResource {
|
||||
private static final Db<Stock> stocks = Repository.STOCKS_DB;
|
||||
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response post(Stock stock) {
|
||||
stocks.save(stock);
|
||||
|
||||
return Response.ok(stock)
|
||||
.build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/{ticker}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response get(@PathParam("ticker") String id) {
|
||||
Optional<Stock> stock = stocks.findById(id);
|
||||
stock.orElseThrow(() -> new IllegalArgumentException("ticker"));
|
||||
|
||||
return Response.ok(stock.get())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
package com.baeldung.jersey.exceptionhandling.rest;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.baeldung.jersey.exceptionhandling.data.Stock;
|
||||
import com.baeldung.jersey.exceptionhandling.data.Wallet;
|
||||
import com.baeldung.jersey.exceptionhandling.repo.Db;
|
||||
import com.baeldung.jersey.exceptionhandling.rest.exceptions.InvalidTradeException;
|
||||
import com.baeldung.jersey.exceptionhandling.rest.exceptions.RestErrorResponse;
|
||||
import com.baeldung.jersey.exceptionhandling.service.Repository;
|
||||
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
@Path("/wallets")
|
||||
public class WalletsResource {
|
||||
private static final Db<Stock> stocks = Repository.STOCKS_DB;
|
||||
private static final Db<Wallet> wallets = Repository.WALLETS_DB;
|
||||
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response post(Wallet wallet) {
|
||||
wallets.save(wallet);
|
||||
|
||||
return Response.ok(wallet)
|
||||
.build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/{id}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response get(@PathParam("id") String id) {
|
||||
Optional<Wallet> wallet = wallets.findById(id);
|
||||
wallet.orElseThrow(IllegalArgumentException::new);
|
||||
|
||||
return Response.ok(wallet.get())
|
||||
.build();
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/{amount}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response putAmount(@PathParam("id") String id, @PathParam("amount") Double amount) {
|
||||
Optional<Wallet> wallet = wallets.findById(id);
|
||||
wallet.orElseThrow(IllegalArgumentException::new);
|
||||
|
||||
if (amount < Wallet.MIN_CHARGE) {
|
||||
throw new InvalidTradeException(Wallet.MIN_CHARGE_MSG);
|
||||
}
|
||||
|
||||
wallet.get()
|
||||
.addBalance(amount);
|
||||
wallets.save(wallet.get());
|
||||
|
||||
return Response.ok(wallet)
|
||||
.build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/{wallet}/buy/{ticker}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response postBuyStock(@PathParam("wallet") String walletId, @PathParam("ticker") String id) {
|
||||
Optional<Stock> stock = stocks.findById(id);
|
||||
stock.orElseThrow(InvalidTradeException::new);
|
||||
|
||||
Optional<Wallet> w = wallets.findById(walletId);
|
||||
w.orElseThrow(InvalidTradeException::new);
|
||||
|
||||
Wallet wallet = w.get();
|
||||
Double price = stock.get()
|
||||
.getPrice();
|
||||
|
||||
if (!wallet.hasFunds(price)) {
|
||||
RestErrorResponse response = new RestErrorResponse();
|
||||
response.setSubject(wallet);
|
||||
response.setMessage("insufficient balance");
|
||||
throw new WebApplicationException(Response.status(Response.Status.NOT_ACCEPTABLE)
|
||||
.entity(response)
|
||||
.build());
|
||||
}
|
||||
|
||||
wallet.addBalance(-price);
|
||||
wallets.save(wallet);
|
||||
|
||||
return Response.ok(wallet)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.baeldung.jersey.exceptionhandling.rest.exceptions;
|
||||
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.ext.ExceptionMapper;
|
||||
|
||||
public class IllegalArgumentExceptionMapper implements ExceptionMapper<IllegalArgumentException> {
|
||||
public static final String DEFAULT_MESSAGE = "an illegal argument was provided";
|
||||
|
||||
@Override
|
||||
public Response toResponse(final IllegalArgumentException exception) {
|
||||
return Response.status(Response.Status.EXPECTATION_FAILED)
|
||||
.entity(build(exception.getMessage()))
|
||||
.type(MediaType.APPLICATION_JSON)
|
||||
.build();
|
||||
}
|
||||
|
||||
private RestErrorResponse build(String message) {
|
||||
RestErrorResponse response = new RestErrorResponse();
|
||||
response.setMessage(DEFAULT_MESSAGE + ": " + message);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package com.baeldung.jersey.exceptionhandling.rest.exceptions;
|
||||
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
public class InvalidTradeException extends WebApplicationException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String MESSAGE = "invalid trade operation";
|
||||
|
||||
public InvalidTradeException() {
|
||||
super(MESSAGE, Response.Status.NOT_ACCEPTABLE);
|
||||
}
|
||||
|
||||
public InvalidTradeException(String detail) {
|
||||
super(MESSAGE + ": " + detail, Response.Status.NOT_ACCEPTABLE);
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package com.baeldung.jersey.exceptionhandling.rest.exceptions;
|
||||
|
||||
public class RestErrorResponse {
|
||||
private Object subject;
|
||||
private String message;
|
||||
|
||||
public RestErrorResponse() {
|
||||
}
|
||||
|
||||
public RestErrorResponse(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public RestErrorResponse(Object subject, String message) {
|
||||
this.subject = subject;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public Object getSubject() {
|
||||
return subject;
|
||||
}
|
||||
|
||||
public void setSubject(Object subject) {
|
||||
this.subject = subject;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package com.baeldung.jersey.exceptionhandling.rest.exceptions;
|
||||
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.ext.ExceptionMapper;
|
||||
|
||||
public class ServerExceptionMapper implements ExceptionMapper<WebApplicationException> {
|
||||
public static final String HTTP_405_MESSAGE = "use one of";
|
||||
|
||||
@Override
|
||||
public Response toResponse(final WebApplicationException exception) {
|
||||
String message;
|
||||
Response response = exception.getResponse();
|
||||
Response.Status status = response.getStatusInfo()
|
||||
.toEnum();
|
||||
|
||||
switch (status) {
|
||||
case METHOD_NOT_ALLOWED:
|
||||
message = HTTP_405_MESSAGE + response.getAllowedMethods();
|
||||
break;
|
||||
case INTERNAL_SERVER_ERROR:
|
||||
message = "internal validation - " + exception;
|
||||
break;
|
||||
default:
|
||||
message = "[unhandled response code] " + exception;
|
||||
}
|
||||
|
||||
return Response.status(status)
|
||||
.entity(status + ": " + message)
|
||||
.type(MediaType.TEXT_PLAIN)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package com.baeldung.jersey.exceptionhandling.service;
|
||||
|
||||
import com.baeldung.jersey.exceptionhandling.data.Stock;
|
||||
import com.baeldung.jersey.exceptionhandling.data.Wallet;
|
||||
import com.baeldung.jersey.exceptionhandling.repo.Db;
|
||||
|
||||
public class Repository {
|
||||
public static Db<Stock> STOCKS_DB = new Db<>();
|
||||
public static Db<Wallet> WALLETS_DB = new Db<>();
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.baeldung.jersey.server;
|
||||
|
||||
import com.baeldung.jersey.client.filter.AddHeaderOnRequestFilter;
|
||||
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.sse.OutboundSseEvent;
|
||||
import jakarta.ws.rs.sse.Sse;
|
||||
import jakarta.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,31 @@
|
||||
package com.baeldung.jersey.server;
|
||||
|
||||
import com.baeldung.jersey.server.config.HelloBinding;
|
||||
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
@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(Response.Status.OK.getStatusCode())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.baeldung.jersey.server;
|
||||
|
||||
import jakarta.ws.rs.FormParam;
|
||||
import jakarta.ws.rs.HeaderParam;
|
||||
import jakarta.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,58 @@
|
||||
package com.baeldung.jersey.server;
|
||||
|
||||
import jakarta.ws.rs.BeanParam;
|
||||
import jakarta.ws.rs.CookieParam;
|
||||
import jakarta.ws.rs.FormParam;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.HeaderParam;
|
||||
import jakarta.ws.rs.MatrixParam;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
|
||||
@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 jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.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 jakarta.ws.rs.NameBinding;
|
||||
|
||||
@NameBinding
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface HelloBinding {
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package com.baeldung.jersey.server.config;
|
||||
|
||||
import com.baeldung.jersey.server.Greetings;
|
||||
import com.baeldung.jersey.server.filter.ResponseServerFilter;
|
||||
|
||||
import jakarta.ws.rs.container.DynamicFeature;
|
||||
import jakarta.ws.rs.container.ResourceInfo;
|
||||
import jakarta.ws.rs.core.FeatureContext;
|
||||
import jakarta.ws.rs.ext.Provider;
|
||||
|
||||
@Provider
|
||||
public class HelloDynamicBinding implements DynamicFeature {
|
||||
|
||||
@Override
|
||||
public void configure(ResourceInfo resourceInfo, FeatureContext context) {
|
||||
|
||||
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 org.glassfish.jersey.server.ResourceConfig;
|
||||
|
||||
import jakarta.ws.rs.ApplicationPath;
|
||||
|
||||
@ApplicationPath("/*")
|
||||
public class ServerConfig extends ResourceConfig {
|
||||
|
||||
public ServerConfig() {
|
||||
packages("com.baeldung.jersey.server");
|
||||
}
|
||||
|
||||
}
|
||||
+16
@@ -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);;
|
||||
}
|
||||
|
||||
}
|
||||
+35
@@ -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 jakarta.validation.Constraint;
|
||||
import jakarta.validation.ConstraintValidator;
|
||||
import jakarta.validation.ConstraintValidatorContext;
|
||||
import jakarta.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 {};
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.baeldung.jersey.server.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.ws.rs.container.ContainerRequestContext;
|
||||
import jakarta.ws.rs.container.ContainerRequestFilter;
|
||||
import jakarta.ws.rs.container.PreMatching;
|
||||
import jakarta.ws.rs.ext.Provider;
|
||||
|
||||
@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");
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.baeldung.jersey.server.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.ws.rs.container.ContainerRequestContext;
|
||||
import jakarta.ws.rs.container.ContainerResponseContext;
|
||||
import jakarta.ws.rs.container.ContainerResponseFilter;
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.baeldung.jersey.server.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.baeldung.jersey.server.config.HelloBinding;
|
||||
|
||||
import jakarta.annotation.Priority;
|
||||
import jakarta.ws.rs.Priorities;
|
||||
import jakarta.ws.rs.container.ContainerRequestContext;
|
||||
import jakarta.ws.rs.container.ContainerRequestFilter;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.ext.Provider;
|
||||
|
||||
@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());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
package com.baeldung.jersey.server.form;
|
||||
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import org.glassfish.jersey.media.multipart.FormDataParam;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
@Path("form")
|
||||
public class FormExampleResource
|
||||
{
|
||||
@GET
|
||||
@Path("/example1")
|
||||
@Produces({MediaType.TEXT_HTML})
|
||||
public InputStream getExample1() throws Exception
|
||||
{
|
||||
File f = new File("src/main/resources/html/example1.html");
|
||||
return new FileInputStream(f);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/example2")
|
||||
@Produces({MediaType.TEXT_HTML})
|
||||
public InputStream getExample2() throws Exception
|
||||
{
|
||||
File f = new File("src/main/resources/html/example2.html");
|
||||
return new FileInputStream(f);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/example1")
|
||||
public String example1(@FormParam("first_name") String firstName,
|
||||
@FormParam("last_name") String lastName,
|
||||
@FormParam("age") String age)
|
||||
{
|
||||
return "Got: First = " + firstName + ", Last = " + lastName + ", Age = " + age;
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/example2")
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
public String example2(@FormDataParam("first_name") String firstName,
|
||||
@FormDataParam("last_name") String lastName,
|
||||
@FormDataParam("age") String age,
|
||||
@FormDataParam("photo") InputStream photo)
|
||||
throws Exception
|
||||
{
|
||||
int len;
|
||||
int size = 1024;
|
||||
byte[] buf;
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
buf = new byte[size];
|
||||
while ((len = photo.read(buf, 0, size)) != -1)
|
||||
bos.write(buf, 0, len);
|
||||
buf = bos.toByteArray();
|
||||
return "Got: First = " + firstName + ", Last = " + lastName + ", Age = " + age + ", Photo (# of bytes) = " + buf.length;
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
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(URI url) {
|
||||
final ResourceConfig rc = new ResourceConfig().packages("com.baeldung.jersey.server");
|
||||
return GrizzlyHttpServerFactory.createHttpServer(URI.create(url.toString()), rc);
|
||||
}
|
||||
}
|
||||
+36
@@ -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 org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import jakarta.ws.rs.ext.Provider;
|
||||
import jakarta.ws.rs.ext.ReaderInterceptor;
|
||||
import jakarta.ws.rs.ext.ReaderInterceptorContext;
|
||||
|
||||
@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 jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import jakarta.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() + "]";
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.baeldung.jersey.server.providers;
|
||||
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.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,119 @@
|
||||
package com.baeldung.jersey.server.rest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
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;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.FormParam;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
@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(Response.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;
|
||||
}
|
||||
}
|
||||
+25
@@ -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<>();
|
||||
|
||||
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.Entry::getValue)
|
||||
.findFirst()
|
||||
.get();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Example 1 using @FormParam</title>
|
||||
</head>
|
||||
<body>
|
||||
<form method="post" action="/form/example1">
|
||||
<label for="first_name">First Name</label>
|
||||
<input id="first_name" name="first_name" type="text">
|
||||
<label for="last_name">Last Name</label>
|
||||
<input id="last_name" name="last_name" type="text">
|
||||
<label for="age">Age</label>
|
||||
<input id="age" name="age" type="text">
|
||||
<input type="submit">
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Example 2 using @FormDataParam</title>
|
||||
</head>
|
||||
<body>
|
||||
<form method="post" action="/form/example2" enctype="multipart/form-data">
|
||||
<label for="first_name">First Name</label>
|
||||
<input id="first_name" name="first_name" type="text">
|
||||
<label for="last_name">Last Name</label>
|
||||
<input id="last_name" name="last_name" type="text">
|
||||
<label for="age">Age</label>
|
||||
<input id="age" name="age" type="text">
|
||||
<label for="photo">Profile Photo</label>
|
||||
<input id="photo" name="photo" type="file">
|
||||
<input type="submit">
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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>
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package com.baeldung.jersey.client;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.glassfish.grizzly.http.server.HttpServer;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.baeldung.jersey.server.http.EmbeddedHttpServer;
|
||||
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
public class JerseyClientIntegrationTest {
|
||||
|
||||
private static int HTTP_OK = 200;
|
||||
|
||||
private static HttpServer httpServer;
|
||||
|
||||
@BeforeAll
|
||||
public static void beforeAllTests() {
|
||||
httpServer = EmbeddedHttpServer.startServer(URI.create("http://localhost:8080/jersey"));
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void afterAllTests() {
|
||||
httpServer.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenGreetingResource_whenCallingHelloGreeting_thenHelloReturned() {
|
||||
String response = JerseyClient.getHelloGreeting();
|
||||
|
||||
assertEquals("hello", response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenGreetingResource_whenCallingHiGreeting_thenHiReturned() {
|
||||
String response = JerseyClient.getHiGreeting();
|
||||
|
||||
assertEquals("hi", response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenGreetingResource_whenCallingCustomGreeting_thenCustomGreetingReturned() {
|
||||
Response response = JerseyClient.getCustomGreeting();
|
||||
|
||||
assertEquals(HTTP_OK, response.getStatus());
|
||||
}
|
||||
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package com.baeldung.jersey.client.listdemo;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.glassfish.jersey.test.JerseyTest;
|
||||
import org.glassfish.jersey.test.TestProperties;
|
||||
import org.junit.Test;
|
||||
|
||||
import jakarta.ws.rs.core.Application;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.UriBuilder;
|
||||
|
||||
public class JerseyListDemoUnitTest extends JerseyTest {
|
||||
|
||||
@Override
|
||||
protected Application configure() {
|
||||
enable(TestProperties.LOG_TRAFFIC);
|
||||
enable(TestProperties.DUMP_ENTITY);
|
||||
return new ListDemoApp();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenList_whenUsingQueryParam_thenPassParamsAsList() {
|
||||
Response response = target("/")
|
||||
.queryParam("items", "item1", "item2")
|
||||
.request()
|
||||
.get();
|
||||
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
|
||||
assertEquals("Received items: [item1, item2]", response.readEntity(String.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenList_whenUsingCommaSeparatedString_thenPassParamsAsList() {
|
||||
Response response = target("/")
|
||||
.queryParam("items", "item1,item2")
|
||||
.request()
|
||||
.get();
|
||||
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
|
||||
assertEquals("Received items: [item1,item2]", response.readEntity(String.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenList_whenUsingUriBuilder_thenPassParamsAsList() {
|
||||
List<String> itemsList = Arrays.asList("item1", "item2");
|
||||
UriBuilder builder = UriBuilder.fromUri("/");
|
||||
for (String item : itemsList) {
|
||||
builder.queryParam("items", item);
|
||||
}
|
||||
URI uri = builder.build();
|
||||
String expectedUri = "/?items=item1&items=item2";
|
||||
assertEquals(expectedUri, uri.toString());
|
||||
}
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
package com.baeldung.jersey.exceptionhandling.rest;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.startsWith;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.glassfish.jersey.server.ResourceConfig;
|
||||
import org.glassfish.jersey.test.JerseyTest;
|
||||
import org.glassfish.jersey.test.TestProperties;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.baeldung.jersey.exceptionhandling.data.Stock;
|
||||
import com.baeldung.jersey.exceptionhandling.data.Wallet;
|
||||
import com.baeldung.jersey.exceptionhandling.rest.exceptions.IllegalArgumentExceptionMapper;
|
||||
import com.baeldung.jersey.exceptionhandling.rest.exceptions.RestErrorResponse;
|
||||
import com.baeldung.jersey.exceptionhandling.rest.exceptions.ServerExceptionMapper;
|
||||
|
||||
import jakarta.ws.rs.client.Entity;
|
||||
import jakarta.ws.rs.client.Invocation;
|
||||
import jakarta.ws.rs.core.Application;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
public class StocksResourceIntegrationTest extends JerseyTest {
|
||||
private static final Entity<String> EMPTY_BODY = Entity.json("");
|
||||
private static final Stock STOCK = new Stock("BAEL", 51.57);
|
||||
private static final String MY_WALLET = "MY-WALLET";
|
||||
private static final Wallet WALLET = new Wallet(MY_WALLET);
|
||||
private static final int INSUFFICIENT_AMOUNT = (int) (Wallet.MIN_CHARGE - 1);
|
||||
|
||||
@Override
|
||||
protected Application configure() {
|
||||
final ResourceConfig resourceConfig = new ResourceConfig();
|
||||
resourceConfig.register(StocksResource.class);
|
||||
resourceConfig.register(WalletsResource.class);
|
||||
resourceConfig.register(IllegalArgumentExceptionMapper.class);
|
||||
resourceConfig.register(ServerExceptionMapper.class);
|
||||
resourceConfig.packages("com.baeldung.jersey.exceptionhandling.rest");
|
||||
return resourceConfig;
|
||||
}
|
||||
|
||||
private Invocation.Builder stocks(String path) {
|
||||
return target("/stocks" + path).request();
|
||||
}
|
||||
|
||||
private Invocation.Builder wallets(String path, Object... args) {
|
||||
return target("/wallets" + String.format(path, args)).request();
|
||||
}
|
||||
|
||||
private Entity<?> entity(Object object) {
|
||||
return Entity.entity(object, MediaType.APPLICATION_JSON_TYPE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenMethodNotAllowed_thenCustomMessage() {
|
||||
Response response = stocks("").get();
|
||||
|
||||
assertEquals(Response.Status.METHOD_NOT_ALLOWED.getStatusCode(), response.getStatus());
|
||||
|
||||
String content = response.readEntity(String.class);
|
||||
assertThat(content, containsString(ServerExceptionMapper.HTTP_405_MESSAGE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenTickerNotExists_thenRestErrorResponse() {
|
||||
Response response = stocks("/TEST").get();
|
||||
|
||||
assertEquals(Response.Status.EXPECTATION_FAILED.getStatusCode(), response.getStatus());
|
||||
|
||||
RestErrorResponse content = response.readEntity(RestErrorResponse.class);
|
||||
assertThat(content.getMessage(), startsWith(IllegalArgumentExceptionMapper.DEFAULT_MESSAGE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAmountLessThanMinimum_whenAddingToWallet_thenInvalidTradeException() {
|
||||
wallets("").post(entity(WALLET));
|
||||
Response response = wallets("/%s/%d", MY_WALLET, INSUFFICIENT_AMOUNT).put(EMPTY_BODY);
|
||||
|
||||
assertEquals(Response.Status.NOT_ACCEPTABLE.getStatusCode(), response.getStatus());
|
||||
|
||||
String content = response.readEntity(String.class);
|
||||
assertThat(content, containsString(Wallet.MIN_CHARGE_MSG));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenInsifficientFunds_whenBuyingStock_thenWebApplicationException() {
|
||||
stocks("").post(entity(STOCK));
|
||||
wallets("").post(entity(WALLET));
|
||||
|
||||
Response response = wallets("/%s/buy/%s", MY_WALLET, STOCK.getId()).post(EMPTY_BODY);
|
||||
assertEquals(Response.Status.NOT_ACCEPTABLE.getStatusCode(), response.getStatus());
|
||||
|
||||
RestErrorResponse content = response.readEntity(RestErrorResponse.class);
|
||||
assertNotNull(content.getSubject());
|
||||
|
||||
HashMap<?, ?> subject = (HashMap<?, ?>) content.getSubject();
|
||||
assertEquals(subject.get("id"), WALLET.getId());
|
||||
assertTrue(WALLET.getBalance() < Wallet.MIN_CHARGE);
|
||||
}
|
||||
}
|
||||
+197
@@ -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.server.ResourceConfig;
|
||||
import org.glassfish.jersey.test.JerseyTest;
|
||||
import org.junit.Test;
|
||||
|
||||
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;
|
||||
|
||||
import jakarta.ws.rs.core.Application;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
public class EchoHeadersIntegrationTest 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");
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package com.baeldung.jersey.server;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.glassfish.jersey.server.ResourceConfig;
|
||||
import org.glassfish.jersey.test.JerseyTest;
|
||||
import org.junit.Test;
|
||||
|
||||
import jakarta.ws.rs.core.Application;
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
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: ", Response.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,53 @@
|
||||
package com.baeldung.jersey.server;
|
||||
|
||||
import static com.baeldung.jersey.server.http.EmbeddedHttpServer.BASE_URI;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
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;
|
||||
|
||||
import jakarta.ws.rs.client.ClientBuilder;
|
||||
import jakarta.ws.rs.client.WebTarget;
|
||||
|
||||
public class ItemsUnitTest {
|
||||
|
||||
private HttpServer server;
|
||||
private WebTarget target;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
server = EmbeddedHttpServer.startServer(BASE_URI);
|
||||
target = ClientBuilder.newClient().target(BASE_URI.toString());
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
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 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;
|
||||
|
||||
import jakarta.ws.rs.client.Entity;
|
||||
import jakarta.ws.rs.core.Application;
|
||||
import jakarta.ws.rs.core.Form;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
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 ", Response.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"));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user