Implementing the JAX-RS service of the adapter
To implement the JAX-RS service of the adapter, you must first implement the JAX-RS application class, then implement the JAX-RS resources classes.
Implementing the JAX-RS application class
About this task
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
public class MyApplication extends Application{
@Override
public Set<Class<?>> getClasses() {
HashSet<Class<?>> classes = new HashSet<Class<?>>();
classes.add(Resource1.class);
classes.add(UsersResource.class);
return classes;
}
@Override
public Set<Object> getSingletons() {
Set<Object> singletons = new HashSet<Object>();
singletons.add(MyResourceSingleton.getInstance());
return singletons;
}
}
An alternative to using the javax.ws.rs.core.Application is to use com.worklight.wink.extensions.MFPJAXRSApplication. In the following example, it is not necessary to put all the resources classes (or singletons) in a list, because MFPJAXRSApplication scans the package that is returned by the getPackageToScan method for JAX-RS resources and creates the list automatically. Additionally, its init method is called by IBM MobileFirst™ Platform Server as soon as the adapter is deployed (before serving has begun) and when the MobileFirst runtime starts up:
import com.worklight.wink.extensions.MFPJAXRSApplication;
public class MyApplication2 extends MFPJAXRSApplication{
@Override
protected void init() throws Exception {
//Perform initialization
}
@Override
protected String getPackageToScan() {
return getClass().getPackage().getName();
}
}
Implementing a JAX-RS resource
About this task
import java.util.ArrayList;
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.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
@Path("/users")
//This is the root URL of the resource ("/users")
public class UsersResource {
//Instead of this static field, it could be a users DAO that works with Database or cloud storage
static ArrayList<User> users = new ArrayList<User>();
@GET
@Produces(MediaType.APPLICATION_JSON)
//This will serve: GET /users
public ArrayList<User> getUsers(){
return users;
}
@Path("/{userId}")
@Produces(MediaType.APPLICATION_JSON)
//This will serve: GET /users/{userId}
public User getUser(@PathParam("userId") String userId){
return findUserById(userId);
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
//This will serve: POST /users
public void addUser(User u) {
users.add(u);
}
@PUT
@Consumes(MediaType.APPLICATION_JSON)
//This will serve: PUT /users
public Response updateUser(User u) {
User user = findUserById(u.getId());
if (user == null){
return Response.status(Status.NOT_FOUND)
.entity("User with ID: "+u.getId()+" not found")
.build();
}
users.remove(user);
users.add(u);
return Response.ok().build();
}
@DELETE
@Path("/{userId}")
//This will serve: DELETE /users/{userId}
public void deleteUser(@PathParam("userId") String userId){
User user = findUserById(userId);
users.remove(user);
}
private User findUserById(String userId) {
//TODO implement...
return null;
}
}
The resource just shown is mapped to
the URL /users and serves the following
requests:Request | Description |
---|---|
GET /users | Gets all users list |
POST /user | Adds a new user |
GET /users/{id} | Gets a specific user with id id |
PUT /users | Updates an existing user |
DELETE /users/{id} | Deletes a user with id id |
The JAX-RS framework does the mapping from the simple Java object User to a JSON object and conversely, making it easier for the service developer to use without taking care of repeating conversion-related code. The implementation also helps in extracting parameter values from the URL and from the query string without having to parse it manually.
Security configuration of a JAX-RS resource
About this task
- Examples
- Using @OAuthSecurity at the resource class level
- To disable the default protection of the UsersResource
class that was used in the previous examples, and make all resource procedures
in this class unprotected, add the OAuthSecurity annotation
to the class definition, and set the annotation's enabled
element to false:
The annotation should be added above the class definition, as shown in the following example:@OAuthSecurity(enabled=false)
@Path("/users") @OAuthSecurity(enabled=false) //This is the root URL of the resource ("/users") public class UsersResource { ...
- Using @OAuthSecurity at the method level
- Suppose that you want to disable protection of the user's resource for read
operations, but protect the add, edit, and delete user operations. To do so, add
the @OAuthSecurity annotation with the
enabled element set to false at the class
level, and then add the annotation to the methods that you want to protect to
override the class annotation. In the following example, the
addUser, updateUser, and
deleteUser methods are protected by an
adminRealm
scope:
@Path("/users") @OAuthSecurity(enabled=false) //This is the root URL of the resource ("/users") public class UsersResource { @GET @Produces(MediaType.APPLICATION_JSON) //This will serve: GET /users public ArrayList<User> getUsers(){ ... } @Path("/{userId}") @Produces(MediaType.APPLICATION_JSON) //This will serve: GET /users/{userId} public User getUser(@PathParam("userId") String userId){ ... } @POST @Consumes(MediaType.APPLICATION_JSON) @OAuthSecurity(scope="adminRealm") //This will serve: POST /users public void addUser(User u) { ... } @PUT @Consumes(MediaType.APPLICATION_JSON) @OAuthSecurity(scope="adminRealm") //This will serve: PUT /users public Response updateUser(User u) { ... } @DELETE @Path("/{userId}") @OAuthSecurity(scope="adminRealm") //This will serve: DELETE /users/{userId} public void deleteUser(@PathParam("userId") String userId){ ... } ... }