/*
* #%L
* FlatPack Demonstration Server
* %%
* Copyright (C) 2012 Perka Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package com.getperka.flatpack.demo.server;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Providers;
import com.getperka.flatpack.FlatPack;
import com.getperka.flatpack.FlatPackEntity;
import com.getperka.flatpack.client.dto.ApiDescription;
import com.getperka.flatpack.jersey.ApiDescriber;
import com.getperka.flatpack.jersey.FlatPackResponse;
/**
* In jax-rs parlance, a Resource contains mappings from HTTP paths to individual methods. The
* container will process the incoming request and invoke a resource method.
*/
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
public class DemoResource {
private final FakeDatabase db;
/**
* Injected by the container and provides access to providers set up by {@link DemoApplication}.
*/
@Context
Providers providers;
public DemoResource(FakeDatabase db) {
this.db = db;
}
/**
* Provide a description of the entities and service methods defined by the web service. Providing
* an endpoint like this is optional, but allows you to use FastTool to automatically generate
* client access libraries.
*/
@GET
@Path("describe")
@FlatPackResponse(ApiDescription.class)
public ApiDescription describeGet() throws IOException {
FlatPack flatpack = providers.getContextResolver(FlatPack.class, MediaType.WILDCARD_TYPE)
.getContext(FlatPack.class);
ApiDescriber api = new ApiDescriber(flatpack, Arrays.asList(DemoResource.class.getMethods()));
ApiDescription description = api.describe();
description.setApiName("Demo");
return description;
}
/**
* This is a simple endpoint just to show a basic jax-rs request endpoint. The method name is
* irrelevant, all mapping information is derived from the method annotation {@link GET} and the
* {@link Path} annotation. Because multiple methods (e.g. {@link POST}, {@link PUT}) may be bound
* to the same path, but with different methods or media types, a suggested coding style is to add
* the discriminators to the end of a descriptive method name.
*
* @param name inserted into the return payload
*/
@GET
@Path("hello")
@Produces(MediaType.TEXT_PLAIN)
public String helloWorldGet(@QueryParam("name") @DefaultValue("World") String name) {
return "Hello " + name + "!";
}
/**
* Return the list of products.
*/
@GET
@Path("products")
@FlatPackResponse({ List.class, Product.class })
public List<Product> productsGet() {
return db.get(Product.class);
}
/**
* Stores or updates Products.
* <p>
* This method demonstrates how ConstraintViolations can be presented to clients in a uniform
* manner. A more complete mechanism for handling escaping {@link ConstraintViolationException} in
* a jax-rs container would be to install an {@link ExceptionMapper} to unwrap the exception and
* report the violations.
*/
@PUT
@Path("products")
@FlatPackResponse(Void.class)
public Response productsPut(List<Product> products) {
FlatPackEntity<Void> toReturn = FlatPackEntity.nullResponse();
Status status = Status.CREATED;
/*
* Call the JSR 303 validator on the entity. In a real system, this might normally be part of
* the database flush.
*/
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
for (Product product : products) {
Set<ConstraintViolation<Product>> violations = validator.validate(product);
if (violations.isEmpty()) {
db.persist(product);
} else {
status = Status.BAD_REQUEST;
toReturn.addConstraintViolations(violations);
}
}
/*
* Full control over the response value is possible by explicitly building a Response object. In
* this case, we want to return a 201 status code and an empty return value. If we were using a
* JSR-303 Validator, any ConstraintViolations could be added to the FlatPackEntity by calling
* addConstraintViolations(), which will map the violations into the errors segment of the
* response.
*/
return Response.status(status).entity(toReturn).build();
}
/**
* Destroy all information in the {@link FakeDatabase} so this resource can be used by tests.
*/
@POST
@Path("reset")
public void reset() {
db.clear();
}
}