Reputation: 1257
I'm new to Jersey (2.22.2), so bear with me please. I am creating a REST service that interfaces with an LDAP server for storing, removing, and retrieving user data. The service acts as a security intermediary by performing encryption/decryption.
There is quite a bit of initialization that must take place before the REST services can be utilized, and I would like to only perform this initialization once (when the application is deployed on the server). So this service would be run as a singleton.
Would appreciate if someone could give me some pointers on the best way to go about doing this? Thanks!
Upvotes: 3
Views: 9208
Reputation:
Jersey 2.22.2 has built-in support altering the lifecycle of its resources. You can use the @Singleton
annotation. Read about it in the official documentation at JAX-RS Application, Resources and Sub-Resources: Life-cycle of Root Resource Classes. Simply put your initialization code in the resource's default constructor.
- Scope: Singleton
- Annotation:
@Singleton
- Annotation full class name:
javax.inject.Singleton
In this scope there is only one instance per jax-rs application. Singleton resource can be either annotated with @Singleton and its class can be registered using the instance of Application. You can also create singletons by registering singleton instances into Application.
Example:
package com.airhacks;
import java.util.Date;
import javax.inject.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
@Path("/hello")
@Singleton
public class HelloWorldService {
public HelloWorldService() throws InterruptedException {
// Some expensive initialization goes here.
Thread.sleep(5000);
System.out.println("Initialized at " + new Date());
}
@GET
public Response getMsg() {
String output = "Hello world at " + new Date();
return Response.status(200).entity(output).build();
}
}
In the above example, the first request took five seconds due to lazy initialization on Glassfish 3, and then all subsequent requests were served immediately.
Upvotes: 7
Reputation: 2394
You can use @Immediate rather than @Singleton in order to ensure that your service gets started as soon as possible. There was some issue at one time where Jersey was not starting the Immediate context by default, but I think that's been resolve by now
Upvotes: 1
Reputation: 9625
User Spring Framework.
https://projects.spring.io/spring-framework/
https://jersey.java.net/documentation/latest/spring.html
There a full working example here:
https://github.com/jersey/jersey/tree/2.22.2/examples/helloworld-spring-webapp
You basically add this dependency to your jersey project and it'll include Spring automatically:
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring3</artifactId>
<version>${project.version}</version>
</dependency>
and then you define your Spring Beans in a file called applicationContext.xml and src/main/resources:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="mySingletonService" class="com.test.MyService"/>
<beans/>
Last But not least, in your actual resource you can inject this singleton service using the @Autowire annotation:
@Path("/resource")
@Component
public class MyResource {
@Autowired
private MyService myService;
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getHello() {
return myService.sayHello();
}
}
Using the @SingletonResource and initializing state within the resource is a terrible, terrible idea IMO. Separation of concerns is important, and keeping state in a REST Resource is just plain awful. Separate the code that deals with your interface (REST) and your business logic by creating let's say an LDAPResource and an LDAPService. The part Spring plays here is just the wiring that otherwise you'd have to instantiate yourself.
Upvotes: 1