[Major] Implemented CRUD for books
This commit is contained in:
parent
2a2a79cb09
commit
2bc31f022e
|
@ -3,9 +3,13 @@
|
|||
|
||||
<Role name="User">
|
||||
<Privilege name="li.strolch.service.api.Service" policy="DefaultPrivilege">
|
||||
<Allow>li.strolch.bookshop.service.CreateBookService</Allow>
|
||||
<Allow>li.strolch.bookshop.service.UpdateBookService</Allow>
|
||||
<Allow>li.strolch.bookshop.service.RemoveBookService</Allow>
|
||||
</Privilege>
|
||||
<Privilege name="li.strolch.model.query.StrolchQuery" policy="DefaultPrivilege">
|
||||
<Allow>internal</Allow>
|
||||
<Allow>li.strolch.bookshop.query.BooksQuery</Allow>
|
||||
</Privilege>
|
||||
</Role>
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
|
||||
<Activity Id="FromStock" Name="From Stock Template" Type="FromStock" TimeOrdering="Series">
|
||||
<ParameterBag Name="objectives" Id="Objectives" Type="Objectives">
|
||||
<Parameter Name="Duration" Id="duration" Value="PT1MS" Type="Duration" />
|
||||
<Parameter Name="Duration" Id="duration" Type="Duration" Value="PT1M" />
|
||||
</ParameterBag>
|
||||
|
||||
<Action Id="validate" Name="Validation of order" Type="Use" ResourceType="Validation" ResourceId="validation" />
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package li.strolch.bookshop;
|
||||
|
||||
public class BookShopConstants {
|
||||
|
||||
public static final String TYPE_BOOK = "Book";
|
||||
|
||||
public static final String BAG_PARAMETERS = "parameters";
|
||||
|
||||
public static final String PARAM_DESCRIPTION = "description";
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package li.strolch.bookshop.query;
|
||||
|
||||
import li.strolch.bookshop.BookShopConstants;
|
||||
import li.strolch.model.query.ResourceQuery;
|
||||
import li.strolch.model.query.StrolchTypeNavigation;
|
||||
|
||||
public class BooksQuery<U> extends ResourceQuery<U> {
|
||||
|
||||
public BooksQuery() {
|
||||
super(new StrolchTypeNavigation(BookShopConstants.TYPE_BOOK));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,189 @@
|
|||
package li.strolch.bookshop.rest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
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.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import li.strolch.bookshop.BookShopConstants;
|
||||
import li.strolch.bookshop.query.BooksQuery;
|
||||
import li.strolch.bookshop.service.CreateBookService;
|
||||
import li.strolch.bookshop.service.RemoveBookService;
|
||||
import li.strolch.bookshop.service.UpdateBookService;
|
||||
import li.strolch.model.Resource;
|
||||
import li.strolch.model.json.StrolchElementToJsonVisitor;
|
||||
import li.strolch.model.query.NameSelection;
|
||||
import li.strolch.model.query.OrSelection;
|
||||
import li.strolch.model.query.ParameterSelection;
|
||||
import li.strolch.model.query.ResourceQuery;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
import li.strolch.privilege.model.Certificate;
|
||||
import li.strolch.rest.RestfulStrolchComponent;
|
||||
import li.strolch.rest.StrolchRestfulConstants;
|
||||
import li.strolch.rest.helper.ResponseUtil;
|
||||
import li.strolch.rest.util.JsonServiceArgument;
|
||||
import li.strolch.rest.util.JsonServiceResult;
|
||||
import li.strolch.service.StringServiceArgument;
|
||||
import li.strolch.service.api.ServiceHandler;
|
||||
import li.strolch.service.api.ServiceResult;
|
||||
import li.strolch.utils.StringMatchMode;
|
||||
import li.strolch.utils.collections.Paging;
|
||||
import li.strolch.utils.helper.StringHelper;
|
||||
|
||||
@Path("books")
|
||||
public class BooksResource {
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response query(@Context HttpServletRequest request, @QueryParam("query") String queryS,
|
||||
@QueryParam("offset") String offsetS, @QueryParam("limit") String limitS) {
|
||||
|
||||
// this is an authenticated method call, thus we can get the certificate from the request:
|
||||
Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
|
||||
|
||||
int offset = StringHelper.isNotEmpty(offsetS) ? Integer.valueOf(offsetS) : 0;
|
||||
int limit = StringHelper.isNotEmpty(limitS) ? Integer.valueOf(limitS) : 20;
|
||||
|
||||
// open the TX with the certificate, using this class as context
|
||||
try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, getClass())) {
|
||||
|
||||
// prepare the query
|
||||
ResourceQuery<JsonObject> query = new BooksQuery<JsonObject>() //
|
||||
// set transformation to JSON
|
||||
.setVisitor(new StrolchElementToJsonVisitor().flat());
|
||||
|
||||
// prepare selections
|
||||
if (StringHelper.isEmpty(queryS)) {
|
||||
query.withAny();
|
||||
} else {
|
||||
OrSelection or = new OrSelection();
|
||||
or.with(ParameterSelection.stringSelection(BookShopConstants.BAG_PARAMETERS,
|
||||
BookShopConstants.PARAM_DESCRIPTION, queryS, StringMatchMode.ci()));
|
||||
or.with(new NameSelection(queryS, StringMatchMode.ci()));
|
||||
|
||||
// add selections
|
||||
query.with(or);
|
||||
}
|
||||
|
||||
// perform the query
|
||||
List<JsonObject> books = tx.doQuery(query);
|
||||
|
||||
// perform paging
|
||||
Paging<JsonObject> page = Paging.asPage(books, offset, limit);
|
||||
|
||||
// return result
|
||||
return ResponseUtil.toResponse(StrolchRestfulConstants.DATA, page.getPage());
|
||||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{id}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response get(@Context HttpServletRequest request, @PathParam("id") String id) {
|
||||
|
||||
// this is an authenticated method call, thus we can get the certificate from the request:
|
||||
Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
|
||||
|
||||
// open the TX with the certificate, using this class as context
|
||||
try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, getClass())) {
|
||||
|
||||
// get the book
|
||||
Resource book = tx.getResourceBy(BookShopConstants.TYPE_BOOK, id);
|
||||
if (book == null)
|
||||
return ResponseUtil.toResponse(Status.NOT_FOUND, "Book " + id + " does not exist!");
|
||||
|
||||
// transform to JSON
|
||||
JsonObject bookJ = book.accept(new StrolchElementToJsonVisitor().flat());
|
||||
|
||||
// return
|
||||
return ResponseUtil.toResponse(StrolchRestfulConstants.DATA, bookJ);
|
||||
}
|
||||
}
|
||||
|
||||
@POST
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response create(@Context HttpServletRequest request, String data) {
|
||||
|
||||
// this is an authenticated method call, thus we can get the certificate from the request:
|
||||
Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
|
||||
|
||||
// parse data to JSON
|
||||
JsonObject jsonData = new JsonParser().parse(data).getAsJsonObject();
|
||||
|
||||
// instantiate the service with the argument
|
||||
CreateBookService svc = new CreateBookService();
|
||||
JsonServiceArgument arg = svc.getArgumentInstance();
|
||||
arg.jsonElement = jsonData;
|
||||
|
||||
// perform the service
|
||||
ServiceHandler serviceHandler = RestfulStrolchComponent.getInstance().getServiceHandler();
|
||||
JsonServiceResult result = serviceHandler.doService(cert, svc, arg);
|
||||
|
||||
// return depending on the result state
|
||||
if (result.isOk())
|
||||
return ResponseUtil.toResponse(StrolchRestfulConstants.DATA, result.getResult());
|
||||
return ResponseUtil.toResponse(result);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("{id}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response update(@Context HttpServletRequest request, @PathParam("id") String id, String data) {
|
||||
|
||||
// this is an authenticated method call, thus we can get the certificate from the request:
|
||||
Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
|
||||
|
||||
// parse data to JSON
|
||||
JsonObject jsonData = new JsonParser().parse(data).getAsJsonObject();
|
||||
|
||||
// instantiate the service with the argument
|
||||
UpdateBookService svc = new UpdateBookService();
|
||||
JsonServiceArgument arg = svc.getArgumentInstance();
|
||||
arg.objectId = id;
|
||||
arg.jsonElement = jsonData;
|
||||
|
||||
// perform the service
|
||||
ServiceHandler serviceHandler = RestfulStrolchComponent.getInstance().getServiceHandler();
|
||||
JsonServiceResult result = serviceHandler.doService(cert, svc, arg);
|
||||
|
||||
// return depending on the result state
|
||||
if (result.isOk())
|
||||
return ResponseUtil.toResponse(StrolchRestfulConstants.DATA, result.getResult());
|
||||
return ResponseUtil.toResponse(result);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("{id}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response update(@Context HttpServletRequest request, @PathParam("id") String id) {
|
||||
|
||||
// this is an authenticated method call, thus we can get the certificate from the request:
|
||||
Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
|
||||
|
||||
// instantiate the service with the argument
|
||||
RemoveBookService svc = new RemoveBookService();
|
||||
StringServiceArgument arg = svc.getArgumentInstance();
|
||||
arg.value = id;
|
||||
|
||||
// perform the service
|
||||
ServiceHandler serviceHandler = RestfulStrolchComponent.getInstance().getServiceHandler();
|
||||
ServiceResult result = serviceHandler.doService(cert, svc, arg);
|
||||
|
||||
// return depending on the result state
|
||||
return ResponseUtil.toResponse(result);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package li.strolch.bookshop.service;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import li.strolch.bookshop.BookShopConstants;
|
||||
import li.strolch.command.AddResourceCommand;
|
||||
import li.strolch.model.Resource;
|
||||
import li.strolch.model.json.FromFlatJsonVisitor;
|
||||
import li.strolch.model.json.StrolchElementToJsonVisitor;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
import li.strolch.rest.util.JsonServiceArgument;
|
||||
import li.strolch.rest.util.JsonServiceResult;
|
||||
import li.strolch.service.api.AbstractService;
|
||||
|
||||
public class CreateBookService extends AbstractService<JsonServiceArgument, JsonServiceResult> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
protected JsonServiceResult getResultInstance() {
|
||||
return new JsonServiceResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonServiceArgument getArgumentInstance() {
|
||||
return new JsonServiceArgument();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JsonServiceResult internalDoService(JsonServiceArgument arg) throws Exception {
|
||||
|
||||
// open a new transaction, using the realm from the argument, or the certificate
|
||||
Resource book;
|
||||
try (StrolchTransaction tx = openArgOrUserTx(arg)) {
|
||||
|
||||
// get a new book "instance" from the template
|
||||
book = tx.getResourceTemplate(BookShopConstants.TYPE_BOOK);
|
||||
|
||||
// map all values from the JSON object into the new book element
|
||||
new FromFlatJsonVisitor().visit(book, arg.jsonElement.getAsJsonObject());
|
||||
|
||||
// add command to store the resource
|
||||
AddResourceCommand cmd = new AddResourceCommand(getContainer(), tx);
|
||||
cmd.setResource(book);
|
||||
tx.addCommand(cmd);
|
||||
|
||||
// notify the TX that it should commit on close
|
||||
tx.commitOnClose();
|
||||
}
|
||||
|
||||
// map the return value to JSON
|
||||
JsonObject result = book.accept(new StrolchElementToJsonVisitor().flat());
|
||||
|
||||
// and return the result
|
||||
return new JsonServiceResult(result);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package li.strolch.bookshop.service;
|
||||
|
||||
import li.strolch.bookshop.BookShopConstants;
|
||||
import li.strolch.command.RemoveResourceCommand;
|
||||
import li.strolch.model.Resource;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
import li.strolch.service.StringServiceArgument;
|
||||
import li.strolch.service.api.AbstractService;
|
||||
import li.strolch.service.api.ServiceResult;
|
||||
|
||||
public class RemoveBookService extends AbstractService<StringServiceArgument, ServiceResult> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
protected ServiceResult getResultInstance() {
|
||||
return new ServiceResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringServiceArgument getArgumentInstance() {
|
||||
return new StringServiceArgument();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ServiceResult internalDoService(StringServiceArgument arg) throws Exception {
|
||||
|
||||
// open a new transaction, using the realm from the argument, or the certificate
|
||||
try (StrolchTransaction tx = openArgOrUserTx(arg)) {
|
||||
|
||||
// get the existing book
|
||||
Resource book = tx.getResourceBy(BookShopConstants.TYPE_BOOK, arg.value, true);
|
||||
|
||||
// add command to remove the resource
|
||||
RemoveResourceCommand cmd = new RemoveResourceCommand(getContainer(), tx);
|
||||
cmd.setResource(book);
|
||||
tx.addCommand(cmd);
|
||||
|
||||
// notify the TX that it should commit on close
|
||||
tx.commitOnClose();
|
||||
}
|
||||
|
||||
// and return the result
|
||||
return ServiceResult.success();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package li.strolch.bookshop.service;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import li.strolch.bookshop.BookShopConstants;
|
||||
import li.strolch.command.UpdateResourceCommand;
|
||||
import li.strolch.model.Resource;
|
||||
import li.strolch.model.Tags.Json;
|
||||
import li.strolch.model.json.FromFlatJsonVisitor;
|
||||
import li.strolch.model.json.StrolchElementToJsonVisitor;
|
||||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
import li.strolch.rest.util.JsonServiceArgument;
|
||||
import li.strolch.rest.util.JsonServiceResult;
|
||||
import li.strolch.service.api.AbstractService;
|
||||
import li.strolch.utils.dbc.DBC;
|
||||
|
||||
public class UpdateBookService extends AbstractService<JsonServiceArgument, JsonServiceResult> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
protected JsonServiceResult getResultInstance() {
|
||||
return new JsonServiceResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonServiceArgument getArgumentInstance() {
|
||||
return new JsonServiceArgument();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JsonServiceResult internalDoService(JsonServiceArgument arg) throws Exception {
|
||||
|
||||
// verify same book
|
||||
DBC.PRE.assertEquals("ObjectId and given Id must be same!", arg.objectId,
|
||||
arg.jsonElement.getAsJsonObject().get(Json.ID).getAsString());
|
||||
|
||||
// open a new transaction, using the realm from the argument, or the certificate
|
||||
Resource book;
|
||||
try (StrolchTransaction tx = openArgOrUserTx(arg)) {
|
||||
|
||||
// get the existing book
|
||||
book = tx.getResourceBy(BookShopConstants.TYPE_BOOK, arg.objectId, true);
|
||||
|
||||
// map all values from the JSON object into the new book element
|
||||
new FromFlatJsonVisitor().visit(book, arg.jsonElement.getAsJsonObject());
|
||||
|
||||
// add command to update the resource
|
||||
UpdateResourceCommand cmd = new UpdateResourceCommand(getContainer(), tx);
|
||||
cmd.setResource(book);
|
||||
tx.addCommand(cmd);
|
||||
|
||||
// notify the TX that it should commit on close
|
||||
tx.commitOnClose();
|
||||
}
|
||||
|
||||
// map the return value to JSON
|
||||
JsonObject result = book.accept(new StrolchElementToJsonVisitor().flat());
|
||||
|
||||
// and return the result
|
||||
return new JsonServiceResult(result);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package li.strolch.bookshop.web;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
import javax.ws.rs.ApplicationPath;
|
||||
import javax.ws.rs.Priorities;
|
||||
|
||||
import org.glassfish.jersey.logging.LoggingFeature;
|
||||
import org.glassfish.jersey.server.ResourceConfig;
|
||||
import org.glassfish.jersey.server.ServerProperties;
|
||||
|
||||
import li.strolch.bookshop.rest.BooksResource;
|
||||
import li.strolch.rest.RestfulStrolchComponent;
|
||||
import li.strolch.rest.StrolchRestfulExceptionMapper;
|
||||
import li.strolch.rest.endpoint.AuthenticationService;
|
||||
import li.strolch.rest.filters.AccessControlResponseFilter;
|
||||
import li.strolch.rest.filters.AuthenticationRequestFilter;
|
||||
import li.strolch.rest.filters.AuthenticationResponseFilter;
|
||||
import li.strolch.rest.filters.CharsetResponseFilter;
|
||||
import li.strolch.rest.filters.HttpCacheResponseFilter;
|
||||
|
||||
@ApplicationPath("rest")
|
||||
public class RestfulApplication extends ResourceConfig {
|
||||
|
||||
public RestfulApplication() {
|
||||
|
||||
// add strolch resources
|
||||
register(AuthenticationService.class);
|
||||
|
||||
// add project resources by package name
|
||||
packages(BooksResource.class.getPackage().getName());
|
||||
|
||||
// filters
|
||||
register(AuthenticationRequestFilter.class, Priorities.AUTHENTICATION);
|
||||
register(AccessControlResponseFilter.class);
|
||||
register(AuthenticationResponseFilter.class);
|
||||
register(HttpCacheResponseFilter.class);
|
||||
|
||||
// log exceptions and return them as plain text to the caller
|
||||
register(StrolchRestfulExceptionMapper.class);
|
||||
|
||||
// the JSON generated is in UTF-8
|
||||
register(CharsetResponseFilter.class);
|
||||
|
||||
RestfulStrolchComponent restfulComponent = RestfulStrolchComponent.getInstance();
|
||||
if (restfulComponent.isRestLogging()) {
|
||||
register(new LoggingFeature(java.util.logging.Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME),
|
||||
Level.SEVERE, LoggingFeature.Verbosity.PAYLOAD_ANY, Integer.MAX_VALUE));
|
||||
|
||||
property(ServerProperties.TRACING, "ALL");
|
||||
property(ServerProperties.TRACING_THRESHOLD, "TRACE");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue