JAVA-29231 Move modules inside existing container modules (#15492)
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
## 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)
|
||||
- [Exception Handling With Jersey](https://www.baeldung.com/java-exception-handling-jersey)
|
||||
- [@FormDataParam vs. @FormParam in Jersey](https://www.baeldung.com/jersey-formdataparam-vs-formparam)
|
||||
- [Add a List as Query Parameter in Jersey](https://www.baeldung.com/java-jersey-list-query-param)
|
||||
@@ -0,0 +1,110 @@
|
||||
<?xml version="1.0"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jersey</artifactId>
|
||||
<name>jersey</name>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>web-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>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.connectors</groupId>
|
||||
<artifactId>jersey-apache-connector</artifactId>
|
||||
<version>${jersey.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.media</groupId>
|
||||
<artifactId>jersey-media-multipart</artifactId>
|
||||
<version>${jersey.version}</version>
|
||||
</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>3.1.1</jersey.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -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"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
/target
|
||||
*.iml
|
||||
@@ -0,0 +1,9 @@
|
||||
## JSF
|
||||
|
||||
This module contains articles about JavaServer Faces (JSF).
|
||||
|
||||
### Relevant Articles:
|
||||
- [Guide to JSF Expression Language 3.0](https://www.baeldung.com/jsf-expression-language-el-3)
|
||||
- [Introduction to JSF EL 2](https://www.baeldung.com/intro-to-jsf-expression-language)
|
||||
- [JavaServer Faces (JSF) with Spring](https://www.baeldung.com/spring-jsf)
|
||||
- [Introduction to Primefaces](https://www.baeldung.com/jsf-primefaces)
|
||||
@@ -0,0 +1,82 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jsf</artifactId>
|
||||
<name>jsf</name>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>web-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
<version>${javax.annotation-api.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JSF -->
|
||||
<dependency>
|
||||
<groupId>com.sun.faces</groupId>
|
||||
<artifactId>jsf-api</artifactId>
|
||||
<version>${com.sun.faces.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.faces</groupId>
|
||||
<artifactId>jsf-impl</artifactId>
|
||||
<version>${com.sun.faces.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.el</groupId>
|
||||
<artifactId>javax.el-api</artifactId>
|
||||
<version>${javax.el.version}</version>
|
||||
</dependency>
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
<version>${javax.servlet-api.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>${maven-war-plugin.version}</version>
|
||||
<configuration>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<!-- Spring -->
|
||||
<org.springframework.version>4.3.4.RELEASE</org.springframework.version>
|
||||
<!-- JSF -->
|
||||
<com.sun.faces.version>2.2.14</com.sun.faces.version>
|
||||
<javax.el.version>3.0.0</javax.el.version>
|
||||
<!-- Other -->
|
||||
<javax.annotation-api.version>1.3.1</javax.annotation-api.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.baeldung.springintegration.config;
|
||||
|
||||
import com.sun.faces.config.FacesInitializer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.WebApplicationInitializer;
|
||||
import org.springframework.web.context.ContextLoaderListener;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import java.util.Set;
|
||||
|
||||
public class MainWebAppInitializer extends FacesInitializer implements WebApplicationInitializer {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MainWebAppInitializer.class);
|
||||
|
||||
@Override
|
||||
public void onStartup(Set<Class<?>> classes, ServletContext servletContext) throws ServletException {
|
||||
super.onStartup(classes, servletContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register and configure all Servlet container components necessary to power the web application.
|
||||
*/
|
||||
@Override
|
||||
public void onStartup(final ServletContext sc) throws ServletException {
|
||||
LOGGER.info("MainWebAppInitializer.onStartup()");
|
||||
sc.setInitParameter("javax.faces.FACELETS_SKIP_COMMENTS", "true");
|
||||
|
||||
// Create the 'root' Spring application context
|
||||
final AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
|
||||
root.register(SpringCoreConfig.class);
|
||||
sc.addListener(new ContextLoaderListener(root));
|
||||
}
|
||||
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.springintegration.config;
|
||||
|
||||
import com.baeldung.springintegration.dao.UserManagementDAO;
|
||||
import com.baeldung.springintegration.dao.UserManagementDAOImpl;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class SpringCoreConfig {
|
||||
|
||||
@Bean
|
||||
public UserManagementDAO userManagementDAO() {
|
||||
return new UserManagementDAOImpl();
|
||||
}
|
||||
}
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
package com.baeldung.springintegration.controllers;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.el.ELContextEvent;
|
||||
import javax.el.ELContextListener;
|
||||
import javax.el.LambdaExpression;
|
||||
import javax.faces.application.Application;
|
||||
import javax.faces.application.FacesMessage;
|
||||
import javax.el.LambdaExpression;
|
||||
import javax.faces.bean.ManagedBean;
|
||||
import javax.faces.bean.ViewScoped;
|
||||
import javax.faces.context.FacesContext;
|
||||
import java.util.Collection;
|
||||
import java.util.Random;
|
||||
|
||||
@ManagedBean(name = "ELBean")
|
||||
@ViewScoped
|
||||
public class ELSampleBean {
|
||||
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
private String pageDescription = "This page demos JSF EL Basics";
|
||||
public static final String constantField = "THIS_IS_NOT_CHANGING_ANYTIME_SOON";
|
||||
private int pageCounter;
|
||||
private Random randomIntGen = new Random();
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
pageCounter = randomIntGen.nextInt();
|
||||
FacesContext.getCurrentInstance()
|
||||
.getApplication()
|
||||
.addELContextListener(new ELContextListener() {
|
||||
@Override
|
||||
public void contextCreated(ELContextEvent evt) {
|
||||
evt.getELContext()
|
||||
.getImportHandler()
|
||||
.importClass("com.baeldung.springintegration.controllers.ELSampleBean");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void save() {
|
||||
|
||||
}
|
||||
|
||||
public static String constantField() {
|
||||
return constantField;
|
||||
}
|
||||
|
||||
public void saveFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public Long multiplyValue(LambdaExpression expr) {
|
||||
Long theResult = (Long) expr.invoke(FacesContext.getCurrentInstance()
|
||||
.getELContext(), pageCounter);
|
||||
return theResult;
|
||||
}
|
||||
|
||||
public void saveByELEvaluation() {
|
||||
firstName = (String) evaluateEL("#{firstName.value}", String.class);
|
||||
FacesContext ctx = FacesContext.getCurrentInstance();
|
||||
FacesMessage theMessage = new FacesMessage("Name component Evaluated: " + firstName);
|
||||
theMessage.setSeverity(FacesMessage.SEVERITY_INFO);
|
||||
ctx.addMessage(null, theMessage);
|
||||
|
||||
}
|
||||
|
||||
private Object evaluateEL(String elExpression, Class<?> clazz) {
|
||||
Object toReturn = null;
|
||||
FacesContext ctx = FacesContext.getCurrentInstance();
|
||||
Application app = ctx.getApplication();
|
||||
toReturn = app.evaluateExpressionGet(ctx, elExpression, clazz);
|
||||
|
||||
return toReturn;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the firstName
|
||||
*/
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param firstName the firstName to set
|
||||
*/
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the lastName
|
||||
*/
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lastName the lastName to set
|
||||
*/
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the pageDescription
|
||||
*/
|
||||
public String getPageDescription() {
|
||||
return pageDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pageDescription the pageDescription to set
|
||||
*/
|
||||
public void setPageDescription(String pageDescription) {
|
||||
this.pageDescription = pageDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the pageCounter
|
||||
*/
|
||||
public int getPageCounter() {
|
||||
return pageCounter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pageCounter the pageCounter to set
|
||||
*/
|
||||
public void setPageCounter(int pageCounter) {
|
||||
this.pageCounter = pageCounter;
|
||||
}
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
package com.baeldung.springintegration.controllers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.el.ELContextEvent;
|
||||
import javax.el.ELContextListener;
|
||||
import javax.faces.bean.ManagedBean;
|
||||
import javax.faces.bean.ViewScoped;
|
||||
|
||||
@ManagedBean(name = "helloPFBean")
|
||||
@ViewScoped
|
||||
public class HelloPFBean {
|
||||
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
|
||||
private String componentSuite;
|
||||
|
||||
private List<Technology> technologies;
|
||||
|
||||
private String inputText;
|
||||
private String outputText;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
firstName = "Hello";
|
||||
lastName = "Primefaces";
|
||||
|
||||
technologies = new ArrayList<Technology>();
|
||||
|
||||
Technology technology1 = new Technology();
|
||||
technology1.setCurrentVersion("10");
|
||||
technology1.setName("Java");
|
||||
|
||||
technologies.add(technology1);
|
||||
|
||||
Technology technology2 = new Technology();
|
||||
technology2.setCurrentVersion("5.0");
|
||||
technology2.setName("Spring");
|
||||
|
||||
technologies.add(technology2);
|
||||
}
|
||||
|
||||
public void onBlurEvent() {
|
||||
outputText = inputText.toUpperCase();
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public String getComponentSuite() {
|
||||
return componentSuite;
|
||||
}
|
||||
|
||||
public void setComponentSuite(String componentSuite) {
|
||||
this.componentSuite = componentSuite;
|
||||
}
|
||||
|
||||
public List<Technology> getTechnologies() {
|
||||
return technologies;
|
||||
}
|
||||
|
||||
public void setTechnologies(List<Technology> technologies) {
|
||||
this.technologies = technologies;
|
||||
}
|
||||
|
||||
public String getInputText() {
|
||||
return inputText;
|
||||
}
|
||||
|
||||
public void setInputText(String inputText) {
|
||||
this.inputText = inputText;
|
||||
}
|
||||
|
||||
public String getOutputText() {
|
||||
return outputText;
|
||||
}
|
||||
|
||||
public void setOutputText(String outputText) {
|
||||
this.outputText = outputText;
|
||||
}
|
||||
|
||||
public class Technology {
|
||||
private String name;
|
||||
private String currentVersion;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getCurrentVersion() {
|
||||
return currentVersion;
|
||||
}
|
||||
|
||||
public void setCurrentVersion(String currentVersion) {
|
||||
this.currentVersion = currentVersion;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.baeldung.springintegration.controllers;
|
||||
|
||||
import javax.faces.bean.ManagedBean;
|
||||
import javax.faces.bean.SessionScoped;
|
||||
|
||||
@ManagedBean(name = "helloPFMBean")
|
||||
@SessionScoped
|
||||
public class HelloPFMBean {
|
||||
|
||||
private String magicWord;
|
||||
|
||||
public String getMagicWord() {
|
||||
return magicWord;
|
||||
}
|
||||
|
||||
public void setMagicWord(String magicWord) {
|
||||
this.magicWord = magicWord;
|
||||
}
|
||||
|
||||
public String go() {
|
||||
if (this.magicWord != null && this.magicWord.toUpperCase()
|
||||
.equals("BAELDUNG")) {
|
||||
return "pm:success";
|
||||
}
|
||||
return "pm:failure";
|
||||
}
|
||||
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
package com.baeldung.springintegration.controllers;
|
||||
|
||||
import com.baeldung.springintegration.dao.UserManagementDAO;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.faces.bean.ManagedBean;
|
||||
import javax.faces.bean.ManagedProperty;
|
||||
import javax.faces.bean.ViewScoped;
|
||||
import javax.faces.context.FacesContext;
|
||||
import java.io.Serializable;
|
||||
|
||||
@ManagedBean(name = "registration")
|
||||
@ViewScoped
|
||||
public class RegistrationBean implements Serializable {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RegistrationBean.class);
|
||||
|
||||
@ManagedProperty(value = "#{userManagementDAO}")
|
||||
transient private UserManagementDAO userDao;
|
||||
private String userName;
|
||||
private String operationMessage;
|
||||
|
||||
public void createNewUser() {
|
||||
try {
|
||||
LOGGER.info("Creating new user");
|
||||
FacesContext context = FacesContext.getCurrentInstance();
|
||||
boolean operationStatus = userDao.createUser(userName);
|
||||
context.isValidationFailed();
|
||||
if (operationStatus) {
|
||||
operationMessage = "User " + userName + " created";
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LOGGER.error("Error registering new user ");
|
||||
ex.printStackTrace();
|
||||
operationMessage = "Error " + userName + " not created";
|
||||
}
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public void setUserDao(UserManagementDAO userDao) {
|
||||
this.userDao = userDao;
|
||||
}
|
||||
|
||||
public UserManagementDAO getUserDao() {
|
||||
return this.userDao;
|
||||
}
|
||||
|
||||
public String getOperationMessage() {
|
||||
return operationMessage;
|
||||
}
|
||||
|
||||
public void setOperationMessage(String operationMessage) {
|
||||
this.operationMessage = operationMessage;
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.baeldung.springintegration.dao;
|
||||
|
||||
public interface UserManagementDAO {
|
||||
|
||||
boolean createUser(String newUserData);
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.baeldung.springintegration.dao;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
@Repository
|
||||
public class UserManagementDAOImpl implements UserManagementDAO {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(UserManagementDAOImpl.class);
|
||||
|
||||
private List<String> users;
|
||||
|
||||
@PostConstruct
|
||||
public void initUserList() {
|
||||
users = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createUser(String newUserData) {
|
||||
if (newUserData != null) {
|
||||
users.add(newUserData);
|
||||
LOGGER.info("User {} successfully created", newUserData);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public UserManagementDAOImpl() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?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>
|
||||
|
||||
<logger name="org.springframework" level="WARN" />
|
||||
<logger name="org.springframework.transaction" level="WARN" />
|
||||
|
||||
<!-- in order to debug some marshalling issues, this needs to be TRACE -->
|
||||
<logger name="org.springframework.web.servlet.mvc" level="WARN" />
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
@@ -0,0 +1,3 @@
|
||||
message.valueRequired = This value is required
|
||||
message.welcome = Baeldung | Register
|
||||
label.saveButton = Save
|
||||
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Context antiJARLocking="true" path="/Baeldung"/>
|
||||
@@ -0,0 +1,45 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
|
||||
<!-- =========== FULL CONFIGURATION FILE ================================== -->
|
||||
|
||||
<faces-config version="2.1"
|
||||
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd">
|
||||
|
||||
<application>
|
||||
<resource-bundle>
|
||||
<base-name>
|
||||
messages
|
||||
</base-name>
|
||||
<var>
|
||||
msg
|
||||
</var>
|
||||
</resource-bundle>
|
||||
<resource-bundle>
|
||||
<base-name>
|
||||
constraints
|
||||
</base-name>
|
||||
<var>
|
||||
constraints
|
||||
</var>
|
||||
</resource-bundle>
|
||||
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
|
||||
|
||||
<navigation-handler>
|
||||
org.primefaces.mobile.application.MobileNavigationHandler
|
||||
</navigation-handler>
|
||||
|
||||
<!-- <default-render-kit-id>PRIMEFACES_MOBILE</default-render-kit-id> -->
|
||||
</application>
|
||||
|
||||
<navigation-rule>
|
||||
<from-view-id>/*</from-view-id>
|
||||
<navigation-case>
|
||||
<from-outcome>home</from-outcome>
|
||||
<to-view-id>/index.xhtml</to-view-id>
|
||||
<redirect/>
|
||||
</navigation-case>
|
||||
</navigation-rule>
|
||||
|
||||
</faces-config>
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version='1.0' encoding='UTF-8' ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:h="http://java.sun.com/jsf/html"
|
||||
xmlns:c="http://java.sun.com/jsp/jstl/core">
|
||||
<h:head>
|
||||
<title>Baeldung | Expression Language 3.0</title>
|
||||
</h:head>
|
||||
<h:body>
|
||||
<h:outputLabel id="valueLabel" for="valueOutput" value="Composite Lambda Evaluation:"/>
|
||||
<h:outputText id="valueOutput" value="#{(cube=(x->x*x*x);cube(4))}"/>
|
||||
<br/>
|
||||
<h:outputLabel id="staticLabel" for="staticFieldOutput" value="Static Field Output:"/>
|
||||
<h:outputText id="staticFieldOutput" value="#{ElBean.constantField}"/>
|
||||
<br/>
|
||||
<h:outputLabel id="avgLabel" for="avg" value="Average of Integer List Value:"/>
|
||||
<h:outputText id="avg" value="#{['1','2','3'].stream().average().get()}"/>
|
||||
<br/>
|
||||
<h:outputLabel id="lambdaLabel" for="lambdaPass" value="Passing Lambda Expressions:"/>
|
||||
<h:outputText id="lambdaPass" value="#{ELBean.multiplyValue(x->x*x*x)}"/>
|
||||
<br/>
|
||||
<c:set var='pageLevelNumberList' value="#{[1,2,3]}"/>
|
||||
<h:outputLabel id="avgPageVarLabel" for="avgPageVar" value="Average of Page-Level Integer List Value:"/>
|
||||
<h:outputText id="avgPageVar" value="#{pageLevelNumberList.stream().average().get()}"/>
|
||||
<br/>
|
||||
<h:panelGrid title="Data Structures" border="3" >
|
||||
<h:dataTable var="streamResult" value="#{pageLevelNumberList.stream().filter(x-> x>1).toList()}">
|
||||
<h:column id="nameCol">
|
||||
<h:outputText id="name" value="#{streamResult}"/>
|
||||
</h:column>
|
||||
</h:dataTable>
|
||||
</h:panelGrid>
|
||||
</h:body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<?xml version='1.0' encoding='UTF-8' ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:h="http://java.sun.com/jsf/html"
|
||||
xmlns:c="http://java.sun.com/jsp/jstl/core"
|
||||
xmlns:f="http://java.sun.com/jsf/core">
|
||||
<h:head>
|
||||
<title>Baeldung | The EL Intro</title>
|
||||
</h:head>
|
||||
|
||||
<h:body>
|
||||
<h:form id="elForm">
|
||||
|
||||
|
||||
<h:messages/>
|
||||
<h:panelGrid columns="2">
|
||||
<h:outputText value="First Name"/>
|
||||
<h:inputText id="firstName" binding="#{firstName}" required="true" value="#{ELBean.firstName}"/>
|
||||
<h:outputText value="Last Name"/>
|
||||
<h:inputText id="lastName" required="true" value="#{ELBean.lastName}"/>
|
||||
<h:outputText value="Save by value binding"/>
|
||||
<h:commandButton value="Save" action="#{ELBean.save}">
|
||||
|
||||
</h:commandButton>
|
||||
<h:outputText value="Evaluate backing bean EL"/>
|
||||
<h:commandButton value="Save" action="#{ELBean.saveByELEvaluation}">
|
||||
</h:commandButton>
|
||||
<h:outputText value="Save by passing value to method"/>
|
||||
<h:commandButton value="Save"
|
||||
action="#{ELBean.saveFirstName(firstName.value.toString().concat('(passed)'))}"/>
|
||||
<h:outputText value="JavaScript (click after saving First Name)"/>
|
||||
<h:button value="Alert" onclick="alert('Hello #{ELBean.firstName}')"/>
|
||||
</h:panelGrid>
|
||||
|
||||
<br/>
|
||||
<h:outputText value="Current Request HTTP Headers:"/>
|
||||
<table border="1">
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<c:forEach items="#{header}" var="header">
|
||||
<tr>
|
||||
<td>#{header.key}</td>
|
||||
<td>#{header.value}</td>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
</table>
|
||||
|
||||
</h:form>
|
||||
</h:body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version='1.0' encoding='UTF-8' ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:h="http://java.sun.com/jsf/html">
|
||||
<h:head>
|
||||
<title><h:outputText value="#{msg['message.welcome']}"/></title>
|
||||
</h:head>
|
||||
<h:body>
|
||||
<h:form>
|
||||
<h:panelGrid id="theGrid" columns="3">
|
||||
<h:outputText value="Username"/>
|
||||
<h:inputText id="firstName" binding="#{userName}" required="true" requiredMessage="#{msg['message.valueRequired']}"
|
||||
value="#{registration.userName}"/>
|
||||
<h:message for="firstName" style="color:red;"/>
|
||||
<h:commandButton value="#{msg['label.saveButton']}" action="#{registration.createNewUser}"
|
||||
process="@this"/>
|
||||
<!--
|
||||
Accessing the Spring bean directly from the page
|
||||
<h:commandButton value="Save"
|
||||
action="#{registration.userDao.createUser(userName.value)}"/>
|
||||
-->
|
||||
<h:outputText value="#{registration.operationMessage}" style="color:green;"/>
|
||||
</h:panelGrid>
|
||||
</h:form>
|
||||
</h:body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:h="http://java.sun.com/jsf/html"
|
||||
xmlns:f="http://java.sun.com/jsf/core"
|
||||
xmlns:ui="http://java.sun.com/jsf/facelets"
|
||||
xmlns:p="http://primefaces.org/ui">
|
||||
|
||||
<h:head>
|
||||
<title>Hello Primefaces</title>
|
||||
</h:head>
|
||||
<h:body>
|
||||
<h:form id="primeForm">
|
||||
|
||||
<p:panelGrid columns="2">
|
||||
<h:outputText value="#{helloPFBean.firstName}" />
|
||||
<h:outputText value="#{helloPFBean.lastName}" />
|
||||
</p:panelGrid>
|
||||
|
||||
<h:panelGrid columns="2">
|
||||
<p:outputLabel for="jsfCompSuite" value="Component Suite" />
|
||||
<p:selectOneRadio id="jsfCompSuite"
|
||||
value="#{helloPFBean.componentSuite}">
|
||||
<f:selectItem itemLabel="ICEfaces" itemValue="ICEfaces" />
|
||||
<f:selectItem itemLabel="RichFaces" itemValue="RichFaces" />
|
||||
</p:selectOneRadio>
|
||||
</h:panelGrid>
|
||||
|
||||
<p:dataTable var="technology" value="#{helloPFBean.technologies}">
|
||||
<p:column headerText="Name">
|
||||
<h:outputText value="#{technology.name}" />
|
||||
</p:column>
|
||||
|
||||
<p:column headerText="Version">
|
||||
<h:outputText value="#{technology.currentVersion}" />
|
||||
</p:column>
|
||||
</p:dataTable>
|
||||
|
||||
<h:panelGrid columns="3">
|
||||
<h:outputText value="Blur event " />
|
||||
<p:inputText id="inputTextId" value="#{helloPFBean.inputText}">
|
||||
<p:ajax event="blur" update="outputTextId"
|
||||
listener="#{helloPFBean.onBlurEvent}" />
|
||||
</p:inputText>
|
||||
<h:outputText id="outputTextId" value="#{helloPFBean.outputText}" />
|
||||
<p:commandButton value="Open Dialog" icon="ui-icon-note"
|
||||
onclick="PF('exDialog').show();">
|
||||
</p:commandButton>
|
||||
</h:panelGrid>
|
||||
|
||||
<p:dialog header="Example dialog" widgetVar="exDialog" minHeight="40">
|
||||
<h:outputText value="Hello Baeldung!" />
|
||||
</p:dialog>
|
||||
|
||||
</h:form>
|
||||
|
||||
</h:body>
|
||||
</html>
|
||||
@@ -0,0 +1,38 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ui="http://java.sun.com/jsf/facelets"
|
||||
xmlns:h="http://java.sun.com/jsf/html"
|
||||
xmlns:f="http://java.sun.com/jsf/core"
|
||||
xmlns:p="http://primefaces.org/ui"
|
||||
xmlns:pm="http://primefaces.org/mobile">
|
||||
<f:view renderKitId="PRIMEFACES_MOBILE" />
|
||||
<h:head>
|
||||
</h:head>
|
||||
<h:body>
|
||||
<pm:page id="enter">
|
||||
<pm:header>
|
||||
<p:outputLabel value="Introduction to PFM"></p:outputLabel>
|
||||
</pm:header>
|
||||
<pm:content>
|
||||
<h:form id="enterForm">
|
||||
<pm:field>
|
||||
<p:outputLabel value="Enter Magic Word"></p:outputLabel>
|
||||
<p:inputText id="magicWord" value="#{helloPFMBean.magicWord}"></p:inputText>
|
||||
</pm:field>
|
||||
<p:commandButton value="Go!" action="#{helloPFMBean.go}"></p:commandButton>
|
||||
</h:form>
|
||||
</pm:content>
|
||||
</pm:page>
|
||||
<pm:page id="success">
|
||||
<pm:content>
|
||||
<p:outputLabel value="Correct!"></p:outputLabel>
|
||||
<p:button value="Back" outcome="pm:enter?transition=flow"></p:button>
|
||||
</pm:content>
|
||||
</pm:page>
|
||||
<pm:page id="failure">
|
||||
<pm:content>
|
||||
<p:outputLabel value="That is not the magic word"></p:outputLabel>
|
||||
<p:button value="Back" outcome="pm:enter?transition=flow"></p:button>
|
||||
</pm:content>
|
||||
</pm:page>
|
||||
</h:body>
|
||||
</html>
|
||||
@@ -26,7 +26,9 @@
|
||||
<module>javax-servlets</module>
|
||||
<module>javax-servlets-2</module>
|
||||
<module>jee-7</module>
|
||||
<module>jersey</module>
|
||||
<module>jooby</module>
|
||||
<module>jsf</module>
|
||||
<module>linkrest</module>
|
||||
<!-- <module>ninja</module> --> <!-- Fixing in JAVA-24584 -->
|
||||
<!-- <module>play-modules</module> --> <!-- Not a maven project -->
|
||||
|
||||
Reference in New Issue
Block a user