JAX-RS Tutorial with Jersey for RESTful Web Services
1. Introduction
In this post, we feature a comprehensive tutorial on JAX-RS with Jersey for RESTful Web Services. Java API for RESTful Web Services (JAX-RS) is a Java programming language API specification that provides support in creating web services according to the Representational State Transfer (REST) architectural pattern. Jersey is Sun’s implementation for JAX-RS. Jersey not only implements the annotations defined in JAX-RS, but also provides its own APIs to simplify the web service creation.
JAX-RS common annotations are:
@Produces
– specify the type of output this web service will produce@Consumes
– specify the MIME media types this web service can consume@Path
– specify the URL path on which this method will be invoked@PathParam
– bind REST-style URL parameters to method arguments@QueryParam
– access the request parameters in query string@POST
– create a resource@GET
– retrieve a resource@PUT
– update the resource@DELETE
– delete the resource
Jersey’s common APIs are:
- ResourceConfig to configure a web application’s resources
- ServerProperties to configure Jersey server properties
- ExtendedExceptionMapper to handle the exceptions
In this tutorial, I will demonstrate how to build RESTful web services utilizing JAX-RS annotations along with Jersey library in a Spring Boot Maven project. These web services include:
- Read service – returns a given user with GET action.
- Search service – displays matching users with GET action.
- Create service – creates a new user with POST action.
- Update service – updates the user with PUT action.
- Delete service – deletes the user with DELETE action.
2. Technologies Used
The example code in this article was built and run using:
- Java 1.8.101 (1.8.x will do fine)
- Maven 3.3.9 (3.3.x will do fine)
- Spring boot 1.5.14 (Higher version will do fine)
- Jersey 2.4.x (Higher version will do fine)
- Eclipse Oxygen (Any Java IDE would work)
- H2 Database
3. Spring Boot Web Application
There are many ways to create a Spring boot Jersey application. The easiest way for me is via the Spring starter tool with the steps below:
- Go to
https://start.spring.io/
. - Select
Maven Project
withJava
and Spring Boot version 1.5.14 and type in Jersey (JAX-RS),JPA
, andH2
in the “search for dependencies” bar. - Enter the group name as
jcg.zheng.demo
and artifact asspring-boot-jersey-demo
. - Click the
Generate Project
button.
A maven project will be generated and downloaded to your workstation. Import it into your Eclipse workspace.
3.1 Dependency
Maven pom.xml
manages the project libraries. The generated pom.xml
contains everything we need for this example.
pom.xml
<?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> <groupId>jcg.zheng.demo</groupId> <artifactId>spring-boot-jersey-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>spring-boot-jersey-demo</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.14.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jersey</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
3.2 Spring Boot Application
In this step, I will update the generated SpringBootJerseyDemoApplication
to include Jersey RESTful resources.
First, I will create UnhandledExceptionMapper
which implements org.glassfish.jersey.spi.ExtendedExceptionMapper
.
UnhandledExceptionMapper.java
package jcg.zheng.demo.restfuljersey; import static java.util.Collections.singletonMap; import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; import java.util.LinkedList; import java.util.List; import javax.ws.rs.InternalServerErrorException; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; import javax.ws.rs.ext.Provider; import org.glassfish.jersey.spi.ExtendedExceptionMapper; @Provider public class UnhandledExceptionMapper implements ExtendedExceptionMapper<Exception> { private List<Class<? extends Exception>> filteredExceptions = new LinkedList<Class<? extends Exception>>(); /* * All ReST services should catch exceptions and repackage them as WebApplicationException * or more specific subclass. */ @Override public Response toResponse(final Exception e) { if (e instanceof WebApplicationException) { if (e instanceof InternalServerErrorException) { return Response.status(INTERNAL_SERVER_ERROR).entity(singletonMap("error", "UNEXPECTED_ERROR")).build(); } final WebApplicationException exception = (WebApplicationException) e; return exception.getResponse(); } return Response.status(INTERNAL_SERVER_ERROR).entity(singletonMap("error", "UNEXPECTED_ERROR" + buildErrorMessage(e))).build(); } @Override public boolean isMappable(final Exception exception) { for (Class<? extends Exception> filteredException : filteredExceptions) { if (filteredException.isAssignableFrom(exception.getClass())) { return false; } } return true; } private String buildErrorMessage(Exception exception) { return exception.getClass().getSimpleName() + ": " + exception.getMessage(); } }
Second, I will create JerseyConfig
which extends from org.glassfish.jersey.server.ResourceConfig
and registers it with UserResourceImpl
and UnhandledExceptionMapper
.
JerseyConfig.java
package jcg.zheng.demo.restfuljersey; import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.server.ServerProperties; import org.springframework.stereotype.Component; import jcg.zheng.demo.restfuljersey.rest.impl.UserResourceImpl; @Component public class JerseyConfig extends ResourceConfig { public JerseyConfig() { registerApplicationProperties(); registerApplicationApis(); } private void registerApplicationApis() { register(UserResourceImpl.class); register(UnhandledExceptionMapper.class); } private void registerApplicationProperties() { property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true); property(ServerProperties.BV_DISABLE_VALIDATE_ON_EXECUTABLE_OVERRIDE_CHECK, true); } }
Lastly, I will update SpringBootJerseyDemoApplication
which extends from org.springframework.boot.web.support.SpringBootServletInitializer
.
SpringBootJerseyDemoApplication.java
package jcg.zheng.demo.restfuljersey; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.support.SpringBootServletInitializer; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @SpringBootApplication @EnableJpaRepositories(basePackages = "jcg.zheng.demo.restfuljersey") public class SpringBootJerseyDemoApplication extends SpringBootServletInitializer { public static void main(String[] args) { new SpringBootJerseyDemoApplication().configure(new SpringApplicationBuilder(SpringBootJerseyDemoApplication.class)) .run(args); } }
4. Jersey Application Packages
I like to organize the application into eight packages:
- rest – define the web service interfaces with JAX-RS API annotations
- rest.impl – annotate
@Component
and implement the resource interface - service – define service to manage the data
- service.impl – annotate
@Service
and implement the service interface - repository – annotate with Spring Data JPA
@Repository
to manage the entities - mapper – annotate with Spring
@Component
and converts between domain and entity - entity – Spring JPA entities
- exception – RESTful web service exceptions
4.1 Rest
We will define the RESTful resource interface UserResource.java
with JAX-RS annotations.
UserResource.java
package jcg.zheng.demo.restfuljersey.rest; import java.util.List; import javax.validation.Valid; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; @Path("/users") @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) public interface UserResource { @GET List getUsers(@QueryParam("companyName") String companyName); @GET @Path(value = "/{userId}") User findUserById(@PathParam("userId") int userId); @POST User createUser(@Valid User request); @PUT @Path(value = "/{userId}") User updateUser( @PathParam("userId")Integer userId, @Valid User request); @DELETE @Path(value = "/{userId}") void deleteUser(@PathParam("userId")Integer userId); }
We will create the User
model class too.
User.java
package jcg.zheng.demo.restfuljersey.rest; import javax.validation.constraints.NotNull; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) @JsonIgnoreProperties(ignoreUnknown = true) @JsonInclude(JsonInclude.Include.NON_EMPTY) public class User { private Integer userId; @NotNull private String firstName; @NotNull private String lastName; @NotNull private String companyName; 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 getCompanyName() { return companyName; } public void setCompanyName(String companyName) { this.companyName = companyName; } public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } }
We will create the implementation class UserResourceImpl
and annotate it with @Component
, so Spring context can manage it.
UserResourceImpl.java
package jcg.zheng.demo.restfuljersey.rest.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import jcg.zheng.demo.restfuljersey.exception.UserNotFoundException; import jcg.zheng.demo.restfuljersey.rest.User; import jcg.zheng.demo.restfuljersey.rest.UserResource; import jcg.zheng.demo.restfuljersey.service.UserService; @Component public class UserResourceImpl implements UserResource { @Autowired private UserService userService; public List<User> getUsers(String companyName) { return userService.searchByCompanyName(companyName); } @Override public User findUserById(int userId) { User found = userService.findById(userId); if (found == null) { throw new UserNotFoundException("invalid userId: " + userId); } return found; } @Override public User createUser(User request) { User saved = userService.save(request); return saved; } @Override public User updateUser(Integer userId, User request) { User found = userService.findById(userId); if (found == null) { throw new UserNotFoundException("invalid userId: " + userId); } if (!StringUtils.isEmpty(request.getCompanyName())) { found.setCompanyName(request.getCompanyName()); } if (!StringUtils.isEmpty(request.getFirstName())) { found.setFirstName(request.getFirstName()); } if (!StringUtils.isEmpty(request.getLastName())) { found.setLastName(request.getLastName()); } return userService.save(found); } @Override public void deleteUser(Integer userId) { User found = userService.findById(userId); if (found == null) { throw new UserNotFoundException("invalid userId: " + userId); } userService.deleteById(userId); } }
4.2 Service
In this step, we will create a UserService
interface with four methods.
UserService.java
package jcg.zheng.demo.restfuljersey.service; import java.util.List; import jcg.zheng.demo.restfuljersey.rest.User; public interface UserService { User save(User user); User findById(Integer personId); List<User> searchByCompanyName(String companyName); void deleteById(Integer personId); }
We will create the implementation class UserServiceImpl
.
UserServiceImpl.java
package jcg.zheng.demo.restfuljersey.service.impl; import java.util.ArrayList; import java.util.List; import javax.transaction.Transactional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import jcg.zheng.demo.restfuljersey.entity.Person; import jcg.zheng.demo.restfuljersey.mapper.UserConverter; import jcg.zheng.demo.restfuljersey.repository.PersonRepository; import jcg.zheng.demo.restfuljersey.rest.User; import jcg.zheng.demo.restfuljersey.service.UserService; @Component @Transactional public class UserServiceImpl implements UserService { @Autowired private PersonRepository personRepo; @Autowired private UserConverter mapper; @Override public User save(User user) { Person saved = personRepo.save(mapper.toEntity(user)); return mapper.toDomain(saved); } @Override public User findById(Integer personId ) { if( personId.intValue() < 0 ) { throw new RuntimeException("Caught unhandle runtime"); } Person found = personRepo.findOne(personId); if( found != null) { return mapper.toDomain(found); } return null; } @Override public List<User> searchByCompanyName(String companyName) { List<Person> persons = personRepo.findByCompany(companyName); List<User> users = new ArrayList<>(); for (Person person:persons) { users.add(mapper.toDomain(person)); } return users; } @Override public void deleteById(Integer personId) { personRepo.delete(personId); } }
4.3 Repository
In this step, we will create a PersonRepository
to manage the Person
entity.
PersonRepository.java
package jcg.zheng.demo.restfuljersey.repository; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import jcg.zheng.demo.restfuljersey.entity.Person; @Repository public interface PersonRepository extends JpaRepository<Person, Integer> { @Query("SELECT person from Person person WHERE person.companyName = :companyName") List<Person> findByCompany(@Param("companyName") String companyName); }
4.4 Mapper
It is a good practice to never return the entity model to the client. Instead, we will create a UserConverter
to convert between the User
and Person
.
UserConverter.java
package jcg.zheng.demo.restfuljersey.mapper; import org.springframework.stereotype.Component; import jcg.zheng.demo.restfuljersey.entity.Person; import jcg.zheng.demo.restfuljersey.rest.User; @Component public class UserConverter { public Person toEntity(final User user) { Person person = new Person(); person.setCompanyName(user.getCompanyName()); person.setfName(user.getFirstName()); person.setlName(user.getLastName()); if (user.getUserId() != null) { person.setPersonId(user.getUserId()); } return person; } public User toDomain(final Person person) { User user = new User(); user.setCompanyName(person.getCompanyName()); user.setFirstName(person.getfName()); user.setLastName(person.getlName()); user.setUserId(person.getPersonId()); return user; } }
4.5 Entity
We will create Person
to model the user’s database entity.
Person.java
package jcg.zheng.demo.restfuljersey.entity; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @Entity public class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int personId; private String fName; private String lName; private String companyName; private String mName; public String getCompanyName() { return companyName; } public void setCompanyName(String companyName) { this.companyName = companyName; } public int getPersonId() { return personId; } public void setPersonId(int personId) { this.personId = personId; } public String getfName() { return fName; } public void setfName(String fName) { this.fName = fName; } public String getlName() { return lName; } public void setlName(String lName) { this.lName = lName; } public String getmName() { return mName; } public void setmName(String mName) { this.mName = mName; } }
4.6 Exception
We will create a UserNotFoundException
for any service when it cannot find the desired person.
UserNotFoundException.java
package jcg.zheng.demo.restfuljersey.exception; import static java.util.Collections.singletonMap; import javax.ws.rs.NotFoundException; import javax.ws.rs.core.Response; public class UserNotFoundException extends NotFoundException{ private static final long serialVersionUID = 3873418545077760440L; public UserNotFoundException(String message) { super(Response.status(Response.Status.NOT_FOUND).entity(singletonMap("error", message)).build()); } }
5. Start Spring Boot Application
Start the web application with the command java -jar target\spring-boot-jersey-demo-0.0.1-SNAPSHOT
.
Confirm that the web application is up and running by viewing the server output.
Server output
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.5.14.RELEASE) 2018-07-11 23:16:49.273 INFO 29288 --- [ main] j.z.d.r.SpringBootJerseyDemoApplication : Starting SpringBootJerseyDemoApplication on SL2LS431841 with PID 29288 (C:\gitworkspace\spring-boot-jersey-demo\target\classes started by Shu.Shan in C:\gitworkspace\spring-boot-jersey-demo) 2018-07-11 23:16:49.280 INFO 29288 --- [ main] j.z.d.r.SpringBootJerseyDemoApplication : No active profile set, falling back to default profiles: default 2018-07-11 23:16:49.430 INFO 29288 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@3f200884: startup date [Wed Jul 11 23:16:49 CDT 2018]; root of context hierarchy 2018-07-11 23:16:50.912 INFO 29288 --- [ main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring 2018-07-11 23:16:52.254 INFO 29288 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http) 2018-07-11 23:16:52.315 INFO 29288 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2018-07-11 23:16:52.316 INFO 29288 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.31 2018-07-11 23:16:52.912 INFO 29288 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2018-07-11 23:16:52.912 INFO 29288 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 3488 ms 2018-07-11 23:16:53.360 INFO 29288 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] 2018-07-11 23:16:53.361 INFO 29288 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] 2018-07-11 23:16:53.361 INFO 29288 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'jcg.zheng.demo.restfuljersey.JerseyConfig' to [/*] 2018-07-11 23:16:54.024 INFO 29288 --- [ main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' 2018-07-11 23:16:54.055 INFO 29288 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ name: default ...] 2018-07-11 23:16:54.172 INFO 29288 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {5.0.12.Final} 2018-07-11 23:16:54.174 INFO 29288 --- [ main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found 2018-07-11 23:16:54.177 INFO 29288 --- [ main] org.hibernate.cfg.Environment : HHH000021: Bytecode provider name : javassist 2018-07-11 23:16:54.250 INFO 29288 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.1.Final} 2018-07-11 23:16:54.579 INFO 29288 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect 2018-07-11 23:16:55.208 INFO 29288 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000227: Running hbm2ddl schema export 2018-07-11 23:16:55.234 INFO 29288 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000230: Schema export complete 2018-07-11 23:16:55.297 INFO 29288 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' 2018-07-11 23:16:55.624 INFO 29288 --- [ main] o.h.h.i.QueryTranslatorFactoryInitiator : HHH000397: Using ASTQueryTranslatorFactory 2018-07-11 23:16:56.134 INFO 29288 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 2018-07-11 23:16:56.183 INFO 29288 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http) 2018-07-11 23:16:56.189 INFO 29288 --- [ main] j.z.d.r.SpringBootJerseyDemoApplication : Started SpringBootJerseyDemoApplication in 7.348 seconds (JVM running for 7.844)
6. Java Clients
There are many ways to build a Java client to invoke the RESTful service. The most common ones are:
6.1 JaxRsClient
In this step, we will use javax.ws.rs.client.Client
to send a POST
request to create a new user.
JaxRsClient.java
package jcg.zheng.demo.restfuljersey.client; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Entity; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import jcg.zheng.demo.restfuljersey.rest.User; public class JaxRsClient { public static void main(String[] argus) { Client client = ClientBuilder.newClient(); WebTarget target = client.target(ClientDataConstants.USER_URI); User data = ClientDataConstants.createDummyUser(); Response ret = target.request().post(Entity.entity(data, MediaType.APPLICATION_JSON)); System.out.println("Create User status: " + ret.getStatus()); String output = ret.readEntity(String.class); System.out.println("Create User with output: " + output); } }
Execute JaxRsClient
as a Java application and you will see the output below:
JaxRsClient output
Create User status: 200 Create User with output: {"userId":1,"firstName":"Mary","lastName":"Zheng","companyName":"JCG"}
6.2 JerseyClient
In this step, we will use org.glassfish.jersey.client.JerseyClient
to send a GET
request to the users that belong to the “JCG” company.
Jersey2Client.java
package jcg.zheng.demo.restfuljersey.client; import javax.ws.rs.core.Response; import org.glassfish.jersey.client.JerseyClient; import org.glassfish.jersey.client.JerseyClientBuilder; public class Jersey2Client { public static void main(String[] argus) { JerseyClient client = JerseyClientBuilder.createClient(); Response response = client.target(ClientDataConstants.USER_URI +"?companyName=JCG").request().get(); System.out.println("Get User status " + response.getStatus()); String output = response.readEntity(String.class); System.out.println("Find User with output: " + output); } }
Execute Jersey2Client
as a Java application and you will see the output below:
Jersey2Client output
Get User status 200 Find User with output: [{"userId":1,"firstName":"Mary","lastName":"Zheng","companyName":"JCG"}]
6.3 SpringRestTemplate
In this step, we will utilize org.springframework.web.client.RestTemplate
to send a POST
request to create a new user.
SpringRestClient.java
package jcg.zheng.demo.restfuljersey.client; import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import jcg.zheng.demo.restfuljersey.rest.User; public class SpringRestClient { public static void main(String[] args) { RestTemplate restTemplate = new RestTemplate(); HttpEntity entity = new HttpEntity(ClientDataConstants.createDummyUser()); ResponseEntity response = restTemplate.exchange(ClientDataConstants.USER_URI, HttpMethod.POST, entity, String.class); System.out.println("Create User status: " + response.getStatusCode()); System.out.println("Create User: " + response.getBody()); } }
Execute SpringRestClient
as a Java application and you will see the output below:
SpringRestClient output
23:26:58.513 [main] DEBUG org.springframework.web.client.RestTemplate - Created POST request for "http://localhost:8080/users" 23:26:58.518 [main] DEBUG org.springframework.web.client.RestTemplate - Setting request Accept header to 23:26:58.547 [main] DEBUG org.springframework.web.client.RestTemplate - Writing [jcg.zheng.demo.restfuljersey.rest.User@64f6106c] using [org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter@553a3d88] 23:26:58.681 [main] DEBUG org.springframework.web.client.RestTemplate - POST request for "http://localhost:8080/users" resulted in 200 (null) 23:26:58.682 [main] DEBUG org.springframework.web.client.RestTemplate - Reading [java.lang.String] as "application/json" using [org.springframework.http.converter.StringHttpMessageConverter@103f852] Create User status: 200 Create User: {"userId":2,"firstName":"Mary","lastName":"Zheng","companyName":"JCG"}
7. Summary
In this example, we created four Spring boot web services utilizing Spring boot, Spring JPA, and Jersey framework in six short steps:
- Generate the Spring boot Jersey JAX-RS project via the starter tool
- Add the
User
model classes - Add the
UserResource
class - Register
UserResource
in Jersey - Start the Spring boot Jersey application
- Test the web services
8. Download the Source Code
This example consists of a Spring boot Jersey RESTful web services application as a Maven project.
You can download the full source code of this example here: JAX-RS Tutorial with Jersey for RESTful Web Services
very helpful for me. just one thing that there is a class ClientDataConstants is missing.
eg.
public class ClientDataConstants {
public static String USER_URI = “http://localhost:8080/users”;
public static User createDummyUser() {
//create a dummy user
User user = new User();
…
return user;
}
}