From 1ab276a329225a7e692ae904a674a3b34d212fdb Mon Sep 17 00:00:00 2001 From: AllanHoejgaardJensen Date: Sun, 5 Feb 2017 00:03:11 +0100 Subject: [PATCH 1/4] corrected content-type in producer --- .../exposure/rs/VirtualAccountServiceExposure.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/VirtualAccountServiceExposure.java b/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/VirtualAccountServiceExposure.java index 5ce833e..6200124 100644 --- a/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/VirtualAccountServiceExposure.java +++ b/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/VirtualAccountServiceExposure.java @@ -72,7 +72,7 @@ public class VirtualAccountServiceExposure { public VirtualAccountServiceExposure() { accountsProducer.put("application/hal+json", this::listServiceGeneration1Version1); - accountsProducer.put("application/hal+json;concept=locations;v=1", this::listServiceGeneration1Version1); + accountsProducer.put("application/hal+json;concept=virtualaccounts;v=1", this::listServiceGeneration1Version1); accountProducers.put("application/hal+json", this::getServiceGeneration1Version2); accountProducers.put("application/hal+json;concept=virtualaccount;v=1", this::getServiceGeneration1Version1); From e70191b878d60756893817d447004f4923676fba Mon Sep 17 00:00:00 2001 From: AllanHoejgaardJensen Date: Sun, 5 Feb 2017 00:07:16 +0100 Subject: [PATCH 2/4] fixed documentation --- .../exposure/rs/VirtualAccountServiceExposure.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/VirtualAccountServiceExposure.java b/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/VirtualAccountServiceExposure.java index 6200124..f0601d1 100644 --- a/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/VirtualAccountServiceExposure.java +++ b/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/VirtualAccountServiceExposure.java @@ -91,10 +91,10 @@ public VirtualAccountServiceExposure() { }, extensions = {@Extension(name = "roles", properties = { @ExtensionProperty(name = "advisor", value = "advisors are allowed getting every virtualaccount"), - @ExtensionProperty(name = "customer", value = "customer only allowed getting own locations")} + @ExtensionProperty(name = "customer", value = "customer only allowed getting own accounts")} )}, - produces = "application/hal+json, application/hal+json;concept=locations;v=1", - notes = "List all locations in a default projection, which is VirtualAccount version 1" + + produces = "application/hal+json, application/hal+json;concept=virtualaccount;v=1", + notes = "List all accounts in a default projection, which is VirtualAccount version 1" + "Supported projections and versions are: " + "VirtualAccounts in version 1 " + "The Accept header for the default version is application/hal+json;concept=virtualaccount;v=1.0.0.... " + @@ -208,8 +208,8 @@ public Response createOrUpdate(@Context UriInfo uriInfo, @Context Request reques } Response listServiceGeneration1Version1(UriInfo uriInfo, Request request) { - List locations = archivist.listAccounts(); - return new EntityResponseBuilder<>(locations, list -> new VirtualAccountsRepresentation(list, uriInfo)) + List accounts = archivist.listAccounts(); + return new EntityResponseBuilder<>(accounts, list -> new VirtualAccountsRepresentation(list, uriInfo)) .name("virtualaccount") .version("1") .maxAge(10) From 03de0705a79335ed86057e89f590227fc5c71509 Mon Sep 17 00:00:00 2001 From: AllanHoejgaardJensen Date: Sun, 5 Feb 2017 12:16:26 +0100 Subject: [PATCH 3/4] initial version of microplans --- .../rs/model/AccountRepresentation.java | 1 - .../rest/bank/account/model/Account.java | 2 +- virtual-account/pom.xml | 5 + .../exposure/rs/MicroPlanServiceExposure.java | 238 ++++++++++++++++++ .../rs/VirtualAccountServiceExposure.java | 28 +-- .../rs/model/MicroPlanRepresentation.java | 131 ++++++++++ .../model/MicroPlanUpdateRepresentation.java | 83 ++++++ .../rs/model/MicroPlansRepresentation.java | 61 +++++ .../bank/virtualaccount/model/MicroPlan.java | 119 +++++++++ .../persistence/VirtualAccountArchivist.java | 34 ++- .../rs/MicroPlanServiceExposureTest.java | 164 ++++++++++++ .../virtualaccount/model/MicroPlanTest.java | 42 ++++ 12 files changed, 881 insertions(+), 27 deletions(-) create mode 100644 virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/MicroPlanServiceExposure.java create mode 100644 virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/model/MicroPlanRepresentation.java create mode 100644 virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/model/MicroPlanUpdateRepresentation.java create mode 100644 virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/model/MicroPlansRepresentation.java create mode 100644 virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/model/MicroPlan.java create mode 100644 virtual-account/src/test/java/dk/sample/rest/bank/virtualaccount/exposure/rs/MicroPlanServiceExposureTest.java create mode 100644 virtual-account/src/test/java/dk/sample/rest/bank/virtualaccount/model/MicroPlanTest.java diff --git a/account/src/main/java/dk/sample/rest/bank/account/exposure/rs/model/AccountRepresentation.java b/account/src/main/java/dk/sample/rest/bank/account/exposure/rs/model/AccountRepresentation.java index cd85596..583c757 100644 --- a/account/src/main/java/dk/sample/rest/bank/account/exposure/rs/model/AccountRepresentation.java +++ b/account/src/main/java/dk/sample/rest/bank/account/exposure/rs/model/AccountRepresentation.java @@ -1,6 +1,5 @@ package dk.sample.rest.bank.account.exposure.rs.model; -import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; diff --git a/account/src/main/java/dk/sample/rest/bank/account/model/Account.java b/account/src/main/java/dk/sample/rest/bank/account/model/Account.java index e66919f..6dea58b 100644 --- a/account/src/main/java/dk/sample/rest/bank/account/model/Account.java +++ b/account/src/main/java/dk/sample/rest/bank/account/model/Account.java @@ -1,6 +1,7 @@ package dk.sample.rest.bank.account.model; import java.math.BigDecimal; +import java.time.Instant; import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -16,7 +17,6 @@ import javax.persistence.UniqueConstraint; import dk.sample.rest.common.persistence.jpa.AbstractAuditable; -import java.time.Instant; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; diff --git a/virtual-account/pom.xml b/virtual-account/pom.xml index 0ef8f27..27c410a 100644 --- a/virtual-account/pom.xml +++ b/virtual-account/pom.xml @@ -20,6 +20,11 @@ common ${project.version} + + dk.sample.rest + account + ${project.version} + org.hibernate hibernate-entitymanager diff --git a/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/MicroPlanServiceExposure.java b/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/MicroPlanServiceExposure.java new file mode 100644 index 0000000..c572746 --- /dev/null +++ b/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/MicroPlanServiceExposure.java @@ -0,0 +1,238 @@ +package dk.sample.rest.bank.virtualaccount.exposure.rs; + +import java.net.URI; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import javax.annotation.security.DeclareRoles; +import javax.annotation.security.PermitAll; +import javax.annotation.security.RolesAllowed; +import javax.ejb.EJB; +import javax.ejb.Stateless; +import javax.validation.constraints.Pattern; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.CacheControl; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Request; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import dk.nykredit.time.CurrentTime; + +import dk.sample.rest.bank.virtualaccount.exposure.rs.model.MicroPlanRepresentation; +import dk.sample.rest.bank.virtualaccount.exposure.rs.model.MicroPlanUpdateRepresentation; +import dk.sample.rest.bank.virtualaccount.exposure.rs.model.MicroPlansRepresentation; +import dk.sample.rest.bank.virtualaccount.model.MicroPlan; +import dk.sample.rest.bank.virtualaccount.persistence.VirtualAccountArchivist; +import dk.sample.rest.common.core.logging.LogDuration; +import dk.sample.rest.common.rs.EntityResponseBuilder; +import dk.sample.rest.common.rs.error.ErrorRepresentation; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import io.swagger.annotations.Authorization; +import io.swagger.annotations.Extension; +import io.swagger.annotations.ExtensionProperty; +import io.swagger.annotations.ResponseHeader; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Exposing Virtul Accounts as REST service + */ +@Stateless +@Path("/microplans") +@PermitAll +@DeclareRoles("advisor") +@Api(value = "/microplans", tags = {"microplan"}) +public class MicroPlanServiceExposure { + private static final Logger LOGGER = LoggerFactory.getLogger(MicroPlanServiceExposure.class); + private static final String ACCOUNT_ROOT = "/accounts/"; + private static final String VIRTUAL_ACCOUNT_ROOT = "/virtualaccounts/"; + + private final Map plansProducer = new HashMap<>(); + private final Map planProducers = new HashMap<>(); + + + @EJB + private VirtualAccountArchivist archivist; + + + public MicroPlanServiceExposure() { + plansProducer.put("application/hal+json", this::listServiceGeneration1Version1); + plansProducer.put("application/hal+json;concept=microplans;v=1", this::listServiceGeneration1Version1); + + planProducers.put("application/hal+json", this::getServiceGeneration1Version1); + planProducers.put("application/hal+json;concept=microplan;v=1", this::getServiceGeneration1Version1); + } + + @GET + @Produces({"application/hal+json", "application/hal+json;concept=microplans;v=1"}) + @ApiOperation(value = "lists accounts", response = MicroPlansRepresentation.class, + authorizations = { + @Authorization(value = "oauth2", scopes = {}), + @Authorization(value = "oauth2-cc", scopes = {}), + @Authorization(value = "oauth2-ac", scopes = {}), + @Authorization(value = "oauth2-rop", scopes = {}), + @Authorization(value = "Bearer") + }, + extensions = {@Extension(name = "roles", properties = { + @ExtensionProperty(name = "advisor", value = "advisors are allowed getting every microplan"), + @ExtensionProperty(name = "customer", value = "customer only allowed getting own plans")} + )}, + produces = "application/hal+json, application/hal+json;concept=microplan;v=1", + notes = "List all plans in a default projection, which is MicroPlan version 1" + + "Supported projections and versions are: " + + "MicroPlans in version 1 " + + "The Accept header for the default version is application/hal+json;concept=microplans;v=1.... " + + "The format for the default version is {....}", nickname = "listMicroPlans") + @ApiResponses(value = { + @ApiResponse(code = 415, message = "Content type not supported.") + }) + public Response list(@Context UriInfo uriInfo, @Context Request request, @HeaderParam("Accept") String accept) { + return plansProducer.getOrDefault(accept, this::handleUnsupportedContentType).getResponse(uriInfo, request); + } + + @GET + @Path("{microplan}") + @Produces({"application/hal+json", "application/hal+json;concept=microplan;v=1"}) + @ApiOperation(value = "gets the information from a single position", response = MicroPlanRepresentation.class, + authorizations = { + @Authorization(value = "oauth2", scopes = {}), + @Authorization(value = "oauth2-cc", scopes = {}), + @Authorization(value = "oauth2-ac", scopes = {}), + @Authorization(value = "oauth2-rop", scopes = {}), + @Authorization(value = "Bearer") + }, + extensions = {@Extension(name = "roles", properties = { + @ExtensionProperty(name = "customer", value = "customer allows getting own information"), + @ExtensionProperty(name = "advisor", value = "advisor allows getting all information")} + )}, + produces = "application/hal+json, application/hal+json;concept=microplan;v=1", + notes = "obtain a single plan " + + " Supported projections and versions are:" + + " MicroPlan in version1 " + + " The format of the default version is .... - The Accept Header is not marked as required in the " + + "swagger - but it is needed - we are working on a solution to that", nickname = "getMicroPlan") + @ApiResponses(value = { + @ApiResponse(code = 404, message = "micro plan not found.") + }) + public Response get(@Context UriInfo uriInfo, @Context Request request, + @PathParam("planname") @Pattern(regexp = "^[a_z]{50}$") String planname, + @HeaderParam("Accept") String accept) { + LOGGER.info("Default version of microplan collected"); + return planProducers.getOrDefault(accept, this::handleUnsupportedContentType) + .getResponse(uriInfo, request, planname); + } + + @PUT + @RolesAllowed("system") + @Path("{microplan}") + @Produces({"application/hal+json"}) + @Consumes("application/json") + @LogDuration(limit = 50) + @ApiOperation(value = "Create new or update existing MicroPlan", response = MicroPlanRepresentation.class, + authorizations = { + @Authorization(value = "oauth2", scopes = {}), + @Authorization(value = "oauth2-cc", scopes = {}), + @Authorization(value = "oauth2-ac", scopes = {}), + @Authorization(value = "oauth2-rop", scopes = {}), + @Authorization(value = "Bearer") + }, + extensions = {@Extension(name = "roles", properties = { + @ExtensionProperty(name = "customer", value = "customer allows getting own customer"), + @ExtensionProperty(name = "system", value = "system allows getting every customer") + })}, + notes = "PUT is used to create a new microplan or used to alter the values attached to the micro plan account", + consumes = "application/json", + produces = "application/hal+json, application/hal+json;concept=microplan;v=1", + nickname = "updateMicroPlan") + @ApiResponses(value = { + @ApiResponse(code = 400, message = "Could not update or create the plan", response = ErrorRepresentation.class), + @ApiResponse(code = 415, message = "The content-Type was not supported"), + @ApiResponse(code = 201, message = "New VirtualAccount Created", response = MicroPlanRepresentation.class, + responseHeaders = { + @ResponseHeader(name = "MicroPlan", description = "a link to the created resource"), + @ResponseHeader(name = "Content-Type", description = "a link to the created resource"), + @ResponseHeader(name = "X-Log-Token", description = "an id for reference purposes in logs etc") + }) + }) + public Response createOrUpdate(@Context UriInfo uriInfo, @Context Request request, + @PathParam("name") @Pattern(regexp = "^[a_z]{50}$") String name, + @ApiParam(value = "plan") MicroPlanUpdateRepresentation plan) { + if (!name.equals(plan.getName())) { + throw new WebApplicationException(Response.Status.BAD_REQUEST); + } + + Optional microPlan = archivist.findPlan(name); + MicroPlan mp; + if (microPlan.isPresent()) { + mp = microPlan.get(); + mp.setDescription(plan.getDescription()); + } else { + mp = new MicroPlan(plan.getName(), plan.getDescription(), plan.getVirtualAccount(), + plan.getPrimaryAccount(), plan.getSecondaryAccount(), plan.getTertiaryAccount()); + } + archivist.save(mp); + + CacheControl cc = new CacheControl(); + int maxAge = 30; + cc.setMaxAge(maxAge); + + return Response.created(URI.create(uriInfo.getPath())) + .entity(new MicroPlanRepresentation(mp, uriInfo)) + .cacheControl(cc).expires(Date.from(CurrentTime.now().plusSeconds(maxAge))) + .status(201) + .type("application/hal+json;concept=MicroPlan;v=1") + .build(); + } + + Response listServiceGeneration1Version1(UriInfo uriInfo, Request request) { + List plans = archivist.listPlans(); + return new EntityResponseBuilder<>(plans, list -> new MicroPlansRepresentation(list, uriInfo)) + .name("microplan") + .version("1") + .maxAge(10) + .build(request); + } + + Response getServiceGeneration1Version1(UriInfo uriInfo, Request request, String planname) { + Optional plan = archivist.findPlan(planname); + if (plan.isPresent()) { + MicroPlan p = plan.get(); + return new EntityResponseBuilder<>(p, pl -> new MicroPlanRepresentation(pl, uriInfo)) + .name("microplan") + .version("1") + .maxAge(10) + .build(request); + } else { + throw new WebApplicationException(Response.Status.NOT_FOUND); + } + } + + interface MicroPlansProducerMethod { + Response getResponse(UriInfo uriInfo, Request request); + } + + interface MicroPlanProducerMethod { + Response getResponse(UriInfo uriInfo, Request request, String name); + } + + Response handleUnsupportedContentType(UriInfo uriInfo, Request request, String... parms) { + return Response.status(Response.Status.UNSUPPORTED_MEDIA_TYPE).build(); + } + +} diff --git a/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/VirtualAccountServiceExposure.java b/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/VirtualAccountServiceExposure.java index f0601d1..07ecbef 100644 --- a/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/VirtualAccountServiceExposure.java +++ b/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/VirtualAccountServiceExposure.java @@ -74,9 +74,8 @@ public VirtualAccountServiceExposure() { accountsProducer.put("application/hal+json", this::listServiceGeneration1Version1); accountsProducer.put("application/hal+json;concept=virtualaccounts;v=1", this::listServiceGeneration1Version1); - accountProducers.put("application/hal+json", this::getServiceGeneration1Version2); + accountProducers.put("application/hal+json", this::getServiceGeneration1Version1); accountProducers.put("application/hal+json;concept=virtualaccount;v=1", this::getServiceGeneration1Version1); - accountProducers.put("application/hal+json;concept=virtualaccount;v=2", this::getServiceGeneration1Version2); } @GET @@ -97,7 +96,7 @@ public VirtualAccountServiceExposure() { notes = "List all accounts in a default projection, which is VirtualAccount version 1" + "Supported projections and versions are: " + "VirtualAccounts in version 1 " + - "The Accept header for the default version is application/hal+json;concept=virtualaccount;v=1.0.0.... " + + "The Accept header for the default version is application/hal+json;concept=virtualaccount;v=1.... " + "The format for the default version is {....}", nickname = "listVirtualAccounts") @ApiResponses(value = { @ApiResponse(code = 415, message = "Content type not supported.") @@ -108,7 +107,7 @@ public Response list(@Context UriInfo uriInfo, @Context Request request, @Header @GET @Path("{virtualAccountNumber}") - @Produces({"application/hal+json", "application/hal+json;concept=virtualaccount;v=1", "application/hal+json;concept=virtualaccount;v=2"}) + @Produces({"application/hal+json", "application/hal+json;concept=virtualaccount;v=1"}) @ApiOperation(value = "gets the information from a single position", response = VirtualAccountRepresentation.class, authorizations = { @Authorization(value = "oauth2", scopes = {}), @@ -124,7 +123,7 @@ public Response list(@Context UriInfo uriInfo, @Context Request request, @Header produces = "application/hal+json, application/hal+json;concept=virtualaccount;v=1, application/hal+json;concept=virtualaccount;v=2", notes = "obtain a single customer back in a default projection, which is VirtualAccount version 2" + " Supported projections and versions are:" + - " VirtualAccount in version1 and VirtualAccount in version 2" + + " VirtualAccount in version1 and VirtualAccount in version 1" + " The format of the default version is .... - The Accept Header is not marked as required in the " + "swagger - but it is needed - we are working on a solution to that", nickname = "getVirtualAccount") @ApiResponses(value = { @@ -203,7 +202,7 @@ public Response createOrUpdate(@Context UriInfo uriInfo, @Context Request reques .entity(new VirtualAccountRepresentation(ac, uriInfo)) .cacheControl(cc).expires(Date.from(CurrentTime.now().plusSeconds(maxAge))) .status(201) - .type("application/hal+json;concept=virtualaccount;v=2") + .type("application/hal+json;concept=virtualaccount;v=1") .build(); } @@ -233,23 +232,6 @@ Response getServiceGeneration1Version1(UriInfo uriInfo, Request request, String .build(request); } - @LogDuration(limit = 50) - Response getServiceGeneration1Version2(UriInfo uriInfo, Request request, String accountNo) { - Long no; - try { - no = Long.parseLong(accountNo); - } catch (NumberFormatException e) { - throw new WebApplicationException(Response.Status.BAD_REQUEST); - } - VirtualAccount virtualaccount = archivist.getAccount(no); - LOGGER.info("Usage - application/hal+json;concept=virtualaccount;v=2 - virtualaccount = " + virtualaccount); - return new EntityResponseBuilder<>(virtualaccount, ac -> new VirtualAccountRepresentation(ac, uriInfo)) - .name("virtualaccount") - .version("2") - .maxAge(60) - .build(request); - } - interface VirtualAccountsProducerMethod { Response getResponse(UriInfo uriInfo, Request request); } diff --git a/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/model/MicroPlanRepresentation.java b/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/model/MicroPlanRepresentation.java new file mode 100644 index 0000000..9303a89 --- /dev/null +++ b/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/model/MicroPlanRepresentation.java @@ -0,0 +1,131 @@ +package dk.sample.rest.bank.virtualaccount.exposure.rs.model; + +import dk.sample.rest.bank.account.exposure.rs.AccountServiceExposure; +import javax.ws.rs.core.UriInfo; + +import dk.nykredit.jackson.dataformat.hal.HALLink; +import dk.nykredit.jackson.dataformat.hal.annotation.Link; + +import dk.sample.rest.bank.virtualaccount.exposure.rs.MicroPlanServiceExposure; +import dk.sample.rest.bank.virtualaccount.exposure.rs.VirtualAccountServiceExposure; +import dk.sample.rest.bank.virtualaccount.model.MicroPlan; + +import io.swagger.annotations.ApiModelProperty; + +/** + * simple representation for micro plan, a microplan is representing a plan for how the configuration for the + * the accumulation of the fonds towards the virtual account + */ +public class MicroPlanRepresentation { + + private String name; + private String description; + + @Link + private HALLink self; + + @Link + private HALLink virtual; + + @Link + private HALLink primaryAccount; + + @Link + private HALLink secondaryAccount; + + @Link + private HALLink tertiaryAccount; + + + public MicroPlanRepresentation(MicroPlan plan, UriInfo uriInfo) { + this.name = plan.getName(); + this.description = plan.getDescription(); + this.self = new HALLink.Builder(uriInfo.getBaseUriBuilder() + .path(MicroPlanServiceExposure.class) + .path(MicroPlanServiceExposure.class, "get") + .build(name)) + .build(); + this.virtual = new HALLink.Builder(uriInfo.getBaseUriBuilder() + .path(VirtualAccountServiceExposure.class) + .path(VirtualAccountServiceExposure.class, "get") + .build(plan.getVirtualAccount())) + .build(); + this.primaryAccount = new HALLink.Builder(uriInfo.getBaseUriBuilder() + .path(AccountServiceExposure.class) + .path(AccountServiceExposure.class, "get") + .build(plan.getPrimaryAccount().substring(0, 4), plan.getPrimaryAccount().substring(5))) + .build(); + if (!"".equals(plan.getSecondaryAccount())) { + this.secondaryAccount = new HALLink.Builder(uriInfo.getBaseUriBuilder() + .path(AccountServiceExposure.class) + .path(AccountServiceExposure.class, "get") + .build(plan.getSecondaryAccount().substring(0, 4), plan.getSecondaryAccount().substring(5))) + .build(); + } + if (!"".equals(plan.getTertiaryAccount())) { + this.tertiaryAccount = new HALLink.Builder(uriInfo.getBaseUriBuilder() + .path(AccountServiceExposure.class) + .path(AccountServiceExposure.class, "get") + .build(plan.getTertiaryAccount().substring(0, 4), plan.getTertiaryAccount().substring(5))) + .build(); + } + } + + @ApiModelProperty( + access = "public", + name = "name", + example = "standard 1-up easy saver", + value = "the easy-save scheme name.") + public String getName() { + return name; + } + + @ApiModelProperty( + access = "public", + name = "description", + example = "standard 1-up easy saver description", + value = "the easy-save scheme description") + public String getDescription() { + return description; + } + + @ApiModelProperty( + access = "public", + name = "self", + notes = "link to the plan itself.") + public HALLink getSelf() { + return self; + } + + @ApiModelProperty( + access = "public", + name = "virtual", + notes = "link to the virtual account itself.") + public HALLink getVirtual() { + return virtual; + } + + @ApiModelProperty( + access = "public", + name = "primaryaccount", + notes = "link to the primary account.") + public HALLink getPrimaryAccount() { + return primaryAccount; + } + + @ApiModelProperty( + access = "public", + name = "secondaryaccount", + notes = "link to the secondary account.") + public HALLink getSecondaryAccount() { + return secondaryAccount; + } + + @ApiModelProperty( + access = "public", + name = "tertiaryAccount", + notes = "link to the tertiary account.") + public HALLink getTertiaryAccount() { + return tertiaryAccount; + } +} diff --git a/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/model/MicroPlanUpdateRepresentation.java b/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/model/MicroPlanUpdateRepresentation.java new file mode 100644 index 0000000..ef92beb --- /dev/null +++ b/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/model/MicroPlanUpdateRepresentation.java @@ -0,0 +1,83 @@ +package dk.sample.rest.bank.virtualaccount.exposure.rs.model; + +import javax.validation.constraints.Pattern; + +import io.swagger.annotations.ApiModelProperty; + + +/** + * the plan that ties a number of accounts (currently 3) account(s) + * together with a virtual savings account ) + */ +public class MicroPlanUpdateRepresentation { + + @Pattern(regexp = "^[a_zA_Z]{50}$") + private String name; + + @Pattern(regexp = "^[.]{100}$") + private String description; + + @Pattern(regexp = "^[0-9]{10}$") + private String virtualAccount; + + @Pattern(regexp = "^[0-9]{4}-[0-9]+$") + private String primaryAccount; + + @Pattern(regexp = "^[0-9]{4}-[0-9]+$") + private String secondaryAccount; + + @Pattern(regexp = "^[0-9]{4}-[0-9]+$") + private String tertiaryAccount; + + @ApiModelProperty( + access = "public", + name = "name", + required = true, + example = "Childrens Microsavings Plan", + value = "the name of the plan.") + public String getName() { + return name; + } + + @ApiModelProperty( + access = "public", + name = "descrition", + required = true, + example = "A Childrens Microsavings Plan, allowing yu to support yours kid to get saving in a comfortable way", + value = "the name of the plan.") + public String getDescription() { + return description; + } + + public String getVirtualAccount() { + return virtualAccount; + } + @ApiModelProperty( + access = "public", + name = "primaryaccountnumber", + required = true, + example = "1234-1234567890", + value = "the primary account number.") + public String getPrimaryAccount() { + return primaryAccount; + } + @ApiModelProperty( + access = "public", + name = "secondaryaccountnumber", + required = true, + example = "1234-1234567890", + value = "the secondary account number.") + public String getSecondaryAccount() { + return secondaryAccount; + } + + @ApiModelProperty( + access = "public", + name = "tertiaryaccountnumber", + required = true, + example = "1234-1234567890", + value = "the tertiary account number.") + public String getTertiaryAccount() { + return tertiaryAccount; + } +} diff --git a/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/model/MicroPlansRepresentation.java b/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/model/MicroPlansRepresentation.java new file mode 100644 index 0000000..bfab294 --- /dev/null +++ b/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/exposure/rs/model/MicroPlansRepresentation.java @@ -0,0 +1,61 @@ +package dk.sample.rest.bank.virtualaccount.exposure.rs.model; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import javax.ws.rs.core.UriInfo; + +import dk.nykredit.jackson.dataformat.hal.HALLink; +import dk.nykredit.jackson.dataformat.hal.annotation.EmbeddedResource; +import dk.nykredit.jackson.dataformat.hal.annotation.Link; +import dk.nykredit.jackson.dataformat.hal.annotation.Resource; +import dk.sample.rest.bank.virtualaccount.exposure.rs.MicroPlanServiceExposure; +import dk.sample.rest.bank.virtualaccount.model.MicroPlan; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * + */ +@Resource +@ApiModel(value = "Microplans ", + description = "a list of Micro Plans") + +public class MicroPlansRepresentation { + + @Link + private HALLink self; + + @EmbeddedResource("microplans") + private Collection plans; + + public MicroPlansRepresentation(List plans, UriInfo uriInfo) { + this.plans = new ArrayList<>(); + this.plans.addAll(plans.stream().map(plan -> new MicroPlanRepresentation(plan, uriInfo)) + .collect(Collectors.toList())); + this.self = new HALLink.Builder(uriInfo.getBaseUriBuilder() + .path(MicroPlanServiceExposure.class) + .build()) + .build(); + } + + @ApiModelProperty( + access = "public", + name = "self", + notes = "link to the list of plans.") + public HALLink getSelf() { + return self; + } + + @ApiModelProperty( + access = "public", + name = "microplans", + value = "micro plan list.") + public Collection getPlans() { + return Collections.unmodifiableCollection(plans); + } + +} diff --git a/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/model/MicroPlan.java b/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/model/MicroPlan.java new file mode 100644 index 0000000..d3f55ec --- /dev/null +++ b/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/model/MicroPlan.java @@ -0,0 +1,119 @@ +package dk.sample.rest.bank.virtualaccount.model; + +import java.util.UUID; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.UniqueConstraint; + +import dk.sample.rest.common.persistence.jpa.AbstractAuditable; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * Very basic modelling of microplans concept to show the basic use of JPA for persistence handling. + */ +@Entity +@Table(name = "MICROPLAN", uniqueConstraints = @UniqueConstraint(columnNames = { "TID" })) +public class MicroPlan extends AbstractAuditable { + + /** + * TID - the technical unique identifier for instance, i.e., primary key. This should NEVER EVER be + * exposed out side the service since it is a key very internal to this service. + */ + @Id + @Column(name = "TID", length = 36, nullable = false, columnDefinition = "CHAR(36)") + private String tId; + + @Column(name = "NAME", length = 36, nullable = false, columnDefinition = "CHAR(50)") + private String name; + + @Column(name = "DESCRIPTION", columnDefinition = "VARCHAR(100)") + private String description; + + @Column(name = "VIRTUALACCOUNTNO", columnDefinition = "VARCHAR(10)") + private String virtualAccount; + + @Column(name = "PRIMARYACCOUNTNO", columnDefinition = "VARCHAR(16)") + private String primaryAccount; + + @Column(name = "SECNODARYACCOUNTNO", columnDefinition = "VARCHAR(16)") + private String secondaryAccount; + + @Column(name = "TERTIARYACCOUNTNO", columnDefinition = "VARCHAR(16)") + private String tertiaryAccount; + + protected MicroPlan() { + // Required by JPA + } + + public MicroPlan(String name, String description, String virtualAccount, + String primaryAccount, String secondaryAccount) { + this(name, description, virtualAccount, primaryAccount, secondaryAccount, ""); + } + + public MicroPlan(String name, String description, String virtualAccount, + String primaryAccount) { + this(name, description, virtualAccount, primaryAccount, "", ""); + } + + public MicroPlan(String name, String description, String virtualAccount, + String primaryAccount, String secondaryAccount, String tertiaryAccount) { + tId = UUID.randomUUID().toString(); + this.name = name; + this.description = description; + this.virtualAccount = virtualAccount; + this.primaryAccount = primaryAccount; + this.secondaryAccount = secondaryAccount; + this.tertiaryAccount = tertiaryAccount; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + + public String getVirtualAccount() { + return virtualAccount; + } + + public String getPrimaryAccount() { + return primaryAccount; + } + + public String getSecondaryAccount() { + return secondaryAccount; + } + + public String getTertiaryAccount() { + return tertiaryAccount; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("name", name) + .append("description", description) + .append("virtualAccount", virtualAccount) + .append("primaryAccount", primaryAccount) + .append("secondaryAccount", secondaryAccount) + .append("tertiaryAccount", tertiaryAccount) + .toString(); + } + +} diff --git a/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/persistence/VirtualAccountArchivist.java b/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/persistence/VirtualAccountArchivist.java index 5dbe995..64a6609 100644 --- a/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/persistence/VirtualAccountArchivist.java +++ b/virtual-account/src/main/java/dk/sample/rest/bank/virtualaccount/persistence/VirtualAccountArchivist.java @@ -1,5 +1,6 @@ package dk.sample.rest.bank.virtualaccount.persistence; +import dk.sample.rest.bank.virtualaccount.model.MicroPlan; import java.util.List; import java.util.Optional; @@ -55,6 +56,7 @@ public VirtualAccount getAccountByAccountNumber(Long vaNumber) { return q.getSingleResult(); } + @LogDuration(limit = 50) public Optional findAccountByAccountNumber(Long no) { try { return Optional.of(getAccount(no)); @@ -63,7 +65,35 @@ public Optional findAccountByAccountNumber(Long no) { } } - public void save(VirtualAccount ac) { - em.persist(ac); + @LogDuration(limit = 50) + public List listPlans() { + TypedQuery q = em.createQuery("select mp from MicroPlan mp", MicroPlan.class); + return q.getResultList(); + } + + @LogDuration(limit = 50) + public MicroPlan getPlan(String name) { + TypedQuery q = em.createQuery("select mp from MicroPlan mp where mp.name=:name", + MicroPlan.class); + q.setParameter("name", name); + return q.getSingleResult(); + } + + @LogDuration(limit = 50) + public Optional findPlan(String name) { + try { + return Optional.of(getPlan(name)); + } catch (Exception e) { + return Optional.empty(); + } + } + + public void save(VirtualAccount account) { + em.persist(account); + } + + public void save(MicroPlan plan) { + em.persist(plan); } + } diff --git a/virtual-account/src/test/java/dk/sample/rest/bank/virtualaccount/exposure/rs/MicroPlanServiceExposureTest.java b/virtual-account/src/test/java/dk/sample/rest/bank/virtualaccount/exposure/rs/MicroPlanServiceExposureTest.java new file mode 100644 index 0000000..cc0cccc --- /dev/null +++ b/virtual-account/src/test/java/dk/sample/rest/bank/virtualaccount/exposure/rs/MicroPlanServiceExposureTest.java @@ -0,0 +1,164 @@ +package dk.sample.rest.bank.virtualaccount.exposure.rs; + +import dk.sample.rest.bank.virtualaccount.exposure.rs.model.MicroPlanRepresentation; +import dk.sample.rest.bank.virtualaccount.exposure.rs.model.MicroPlanUpdateRepresentation; +import dk.sample.rest.bank.virtualaccount.exposure.rs.model.MicroPlansRepresentation; +import dk.sample.rest.bank.virtualaccount.exposure.rs.model.VirtualAccountRepresentation; +import dk.sample.rest.bank.virtualaccount.exposure.rs.model.VirtualAccountUpdateRepresentation; +import dk.sample.rest.bank.virtualaccount.exposure.rs.model.VirtualAccountsRepresentation; +import dk.sample.rest.bank.virtualaccount.model.MicroPlan; +import dk.sample.rest.bank.virtualaccount.model.VirtualAccount; +import dk.sample.rest.bank.virtualaccount.persistence.VirtualAccountArchivist; +import dk.sample.rest.common.test.rs.UriBuilderFactory; +import java.math.BigDecimal; +import java.net.URI; +import java.util.Arrays; +import java.util.Optional; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Request; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class MicroPlanServiceExposureTest { + + @Mock + VirtualAccountArchivist archivist; + + @InjectMocks + MicroPlanServiceExposure service; + + @Test + public void testList() { + Request request = mock(Request.class); + + UriInfo ui = mock(UriInfo.class); + when(ui.getBaseUriBuilder()).then(new UriBuilderFactory(URI.create("http://mock"))); + + when(archivist.listPlans()) + .thenReturn(Arrays.asList( + new MicroPlan("testPlan", "A sample savingplan", "11", "1234-1234567890"), + new MicroPlan("testPlan", "A sample savingplan", "11", "1234-1234567890"), + new MicroPlan("testPlan", "A sample savingplan", "11", "1234-1234567890"))); + + Response response = service.list(ui, request, "application/hal+json"); + MicroPlansRepresentation plans = (MicroPlansRepresentation) response.getEntity(); + + assertEquals(3, plans.getPlans().size()); + assertEquals("http://mock/microplans", plans.getSelf().getHref()); + + response = service.list(ui, request, "application/hal+json;concept=non.existing;type"); + assertEquals(415,response.getStatus()); + + } + + @Test + public void testGet() { + Request request = mock(Request.class); + + UriInfo ui = mock(UriInfo.class); + when(ui.getBaseUriBuilder()).then(new UriBuilderFactory(URI.create("http://mock"))); + + when(archivist.findPlan("testPlan")).thenReturn( + Optional.of(new MicroPlan("testPlan", "A sample savingplan", "11", "1234-1234567890"))); + + MicroPlanRepresentation plan = (MicroPlanRepresentation) service.get(ui, request, + "testPlan","application/hal+json" + ).getEntity(); + + assertEquals("testPlan", plan.getName()); + assertEquals("A sample savingplan", plan.getDescription()); + assertEquals("http://mock/microplans/" + plan.getName(), + plan.getSelf().getHref()); + assertEquals("http://mock/virtualaccounts/11", plan.getVirtual().getHref()); + assertEquals("http://mock/accounts/1234-1234567890", plan.getPrimaryAccount().getHref()); + + Response response = service.get(ui, request, "1","application/hal+json;concept=location;v=0"); + assertEquals(415,response.getStatus()); + } + + + @Test + public void testCreate() throws Exception { + Request request = mock(Request.class); + UriInfo ui = mock(UriInfo.class); + when(ui.getBaseUriBuilder()).then(new UriBuilderFactory(URI.create("http://mock"))); + when(ui.getPath()).thenReturn("http://mock"); + + MicroPlanUpdateRepresentation plan = mock(MicroPlanUpdateRepresentation.class); + when(plan.getName()).thenReturn("newPlan"); + when(plan.getDescription()).thenReturn("describe it"); + when(plan.getVirtualAccount()).thenReturn("5123"); + when(plan.getPrimaryAccount()).thenReturn("4767-98989898989"); + when(plan.getSecondaryAccount()).thenReturn("4767-232323232323"); + when(plan.getTertiaryAccount()).thenReturn("4767-565656565665"); + + when(archivist.findPlan("newPlan")).thenReturn(Optional.empty()); + + MicroPlanRepresentation resp = (MicroPlanRepresentation) service.createOrUpdate(ui, request, + "newPlan", plan).getEntity(); + assertEquals("newPlan", resp.getName()); + assertEquals("describe it", plan.getDescription()); + assertEquals("5123", plan.getVirtualAccount()); + assertEquals("4767-98989898989", plan.getPrimaryAccount()); + assertEquals("4767-232323232323", plan.getSecondaryAccount()); + assertEquals("4767-565656565665", plan.getTertiaryAccount()); + assertEquals("http://mock/microplans/" + plan.getName(), resp.getSelf().getHref()); + assertEquals("http://mock/virtualaccounts/" + plan.getVirtualAccount(), resp.getVirtual().getHref()); + assertEquals("http://mock/accounts/" + plan.getPrimaryAccount(), resp.getPrimaryAccount().getHref()); + assertEquals("http://mock/accounts/" + plan.getSecondaryAccount(), resp.getSecondaryAccount().getHref()); + assertEquals("http://mock/accounts/" + plan.getTertiaryAccount(), resp.getTertiaryAccount().getHref()); + } + + + @Test + public void testUpdate() throws Exception { + Request request = mock(Request.class); + UriInfo ui = mock(UriInfo.class); + when(ui.getBaseUriBuilder()).then(new UriBuilderFactory(URI.create("http://mock"))); + when(ui.getPath()).thenReturn("http://mock"); + + MicroPlan plan = new MicroPlan("testPlan", "A sample savingplan", "11", "1234-1234567890", + "1234-555566667777", "5555-4567890987"); + + MicroPlanUpdateRepresentation planUpdate = mock(MicroPlanUpdateRepresentation.class); + when(planUpdate.getName()).thenReturn("plantocreate"); + when(planUpdate.getDescription()).thenReturn(" The New Plan to be created"); + + when(archivist.findPlan("plantocreate")).thenReturn(Optional.of(plan)); + + MicroPlanRepresentation resp = ( MicroPlanRepresentation) service.createOrUpdate(ui, request, + "plantocreate", planUpdate).getEntity(); + + assertEquals(plan.getName(), resp.getName()); + assertEquals(plan.getDescription(), resp.getDescription()); + assertEquals("http://mock/microplans/" + plan.getName(), resp.getSelf().getHref()); + assertEquals("http://mock/virtualaccounts/" + plan.getVirtualAccount(), resp.getVirtual().getHref()); + assertEquals("http://mock/accounts/" + plan.getPrimaryAccount(), resp.getPrimaryAccount().getHref()); + assertEquals("http://mock/accounts/" + plan.getSecondaryAccount(), resp.getSecondaryAccount().getHref()); + assertEquals("http://mock/accounts/" + plan.getTertiaryAccount(), resp.getTertiaryAccount().getHref()); + } + + + @Test(expected = WebApplicationException.class) + public void testCreateInvalidRequest() throws Exception { + Request request = mock(Request.class); + UriInfo ui = mock(UriInfo.class); + + MicroPlanUpdateRepresentation account = mock(MicroPlanUpdateRepresentation.class); + when(account.getName()).thenReturn("noplan"); + + service.createOrUpdate(ui, request, "otherplan", account); + fail("Should have thrown exception before this step"); + } +} diff --git a/virtual-account/src/test/java/dk/sample/rest/bank/virtualaccount/model/MicroPlanTest.java b/virtual-account/src/test/java/dk/sample/rest/bank/virtualaccount/model/MicroPlanTest.java new file mode 100644 index 0000000..7cb7e0a --- /dev/null +++ b/virtual-account/src/test/java/dk/sample/rest/bank/virtualaccount/model/MicroPlanTest.java @@ -0,0 +1,42 @@ +package dk.sample.rest.bank.virtualaccount.model; + +import java.math.BigDecimal; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class MicroPlanTest { + + @Test + public void testNewMimimalPlan() { + MicroPlan mp = new MicroPlan("testPlan", "A sample savingplan", "11", "1234-1234567890"); + assertEquals("testPlan", mp.getName()); + assertEquals("A sample savingplan", mp.getDescription()); + assertEquals("11", mp.getVirtualAccount()); + assertEquals("1234-1234567890", mp.getPrimaryAccount()); + assertEquals("", mp.getSecondaryAccount()); + assertEquals("", mp.getTertiaryAccount()); + } + + @Test + public void testNewDualAccountPlan() { + MicroPlan mp = new MicroPlan("testPlan", "A sample savingplan", "11", "1234-1234567890","2345-0987654321"); + assertEquals("testPlan", mp.getName()); + assertEquals("A sample savingplan", mp.getDescription()); + assertEquals("11", mp.getVirtualAccount()); + assertEquals("1234-1234567890", mp.getPrimaryAccount()); + assertEquals("2345-0987654321", mp.getSecondaryAccount()); + assertEquals("", mp.getTertiaryAccount()); + } + + @Test + public void testNewTrippleAccountPlan() { + MicroPlan mp = new MicroPlan("testPlan", "A sample savingplan", "11", "1234-1234567890","2345-0987654321", "3456-123409856"); + assertEquals("testPlan", mp.getName()); + assertEquals("A sample savingplan", mp.getDescription()); + assertEquals("11", mp.getVirtualAccount()); + assertEquals("1234-1234567890", mp.getPrimaryAccount()); + assertEquals("2345-0987654321", mp.getSecondaryAccount()); + assertEquals("3456-123409856", mp.getTertiaryAccount()); + } +} From 3768b3223d2412cf9f44a46d254b3bf50a9d5f4c Mon Sep 17 00:00:00 2001 From: AllanHoejgaardJensen Date: Sun, 5 Feb 2017 13:03:42 +0100 Subject: [PATCH 4/4] added simple tests --- .../VirtualAccountServiceExposureIT.java | 87 ++++++++++++++++++ src/test/h2-data/virtualaccount.h2.db | Bin 1095680 -> 1095680 bytes 2 files changed, 87 insertions(+) create mode 100644 rest-services/src/test/java/dk/sample/rest/bank/virtualaccount/VirtualAccountServiceExposureIT.java diff --git a/rest-services/src/test/java/dk/sample/rest/bank/virtualaccount/VirtualAccountServiceExposureIT.java b/rest-services/src/test/java/dk/sample/rest/bank/virtualaccount/VirtualAccountServiceExposureIT.java new file mode 100644 index 0000000..870499c --- /dev/null +++ b/rest-services/src/test/java/dk/sample/rest/bank/virtualaccount/VirtualAccountServiceExposureIT.java @@ -0,0 +1,87 @@ +package dk.sample.rest.bank.virtualaccount; + +import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider; +import dk.sample.rest.common.core.diagnostic.ContextInfo; +import dk.sample.rest.common.core.diagnostic.DiagnosticContext; +import java.io.UnsupportedEncodingException; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Base64; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ThreadLocalRandom; +import javax.ws.rs.BadRequestException; +import javax.ws.rs.WebApplicationException; +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.MultivaluedHashMap; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +@SuppressWarnings("unchecked") +public class VirtualAccountServiceExposureIT { + + private DiagnosticContext dCtx; + + @Before + public void setupLogToken() { + dCtx = new DiagnosticContext(new ContextInfo() { + @Override + public String getLogToken() { + return "junit-" + System.currentTimeMillis(); + } + + @Override + public void setLogToken(String s) { + + } + }); + dCtx.start(); + } + + @After + public void removeLogToken() { + dCtx.stop(); + } + + @Test(expected = WebApplicationException.class) + public void testListAccounts() { + WebTarget target = ClientBuilder.newClient().register(JacksonJaxbJsonProvider.class).target("http://localhost:7001/sample"); + Map response = target.path("virtualaccounts") + .request() + .accept("application/hal+json") + .header("X-Client-Version", "1.0.0") + .header("X-Service-Generation", "1") + .header("X-Log-Token", DiagnosticContext.getLogToken()) + .get(Map.class); + + fail("Should not find anything"); + } + + @Test(expected = WebApplicationException.class) + public void testListPlans() { + WebTarget target = ClientBuilder.newClient().register(JacksonJaxbJsonProvider.class).target("http://localhost:7001/sample"); + Map response = target.path("microplans") + .request() + .accept("application/hal+json") + .header("X-Client-Version", "1.0.0") + .header("X-Service-Generation", "1") + .header("X-Log-Token", DiagnosticContext.getLogToken()) + .get(Map.class); + + fail("Should not find anything"); + } +} diff --git a/src/test/h2-data/virtualaccount.h2.db b/src/test/h2-data/virtualaccount.h2.db index 76d4c8a8203dfb97828e1da8a76ac9eaff03287d..f27816ae4dcd98a0f8700bd2a2eeb2bd4837c543 100644 GIT binary patch delta 335 zcmZqp;MDNJX#s~s-YK8I3}E2=1W2g@F)I+WZx&2=!H!>cl7tIW1N%nDUF?$-_!zk+ z^D9U*3$XKV)>VjSn;6hM`NA2+$p-2d4B3TJp{4>&XX0Y~4dk(b>;Pg8Am#*OE+FOx zVjdvo-7M;Gj-8i*gWD6x1Gz?(W3%GTFYG)VT&N=En+muc*!dZlfaZ#B7TWNRz1iSq zyTMIHAZ7w$W*}w(Vpbq#17da{<^W<&Am##MZXo6XVqPHTTW)ZZ{|2WZa|+Nx27Y#+ wjo-!j1^oqpJTV3q2F6{CY`Zr)u3?+J|GeYmg5wh=+nw^7>~KkIvEoe*02C!wGynhq delta 6120 zcmeI0e{37&8OPuE{QAzZlh{s^ChHIU#%&VYIVb0fe~OLPi7&;(vD3sZwAygeBb0aX8BiqFyl|21zFjxXK0w@&jTIal%k%*^nZ&5eFp>ciGWY zSt!lxl+^K_rSZaXZT=F{3BM6u623PV{vsBlvh4LsUiU=LSjO%3OnTj8AWF}d!-3UT9BZ8d9)0n^dEao3SgL!%ullRYI^3Zdb)IX1P zGv~3+`2yx1coE|d=ECQ&O1fxU-BUOmODe-O8SafKbSTvui}rQJ5`E!hG!aiL`;>T+ zh9eQ$mxzxfhr?0$Sujcsg!d}9hW4dy^9A~PqDm+p@y8@@bWdQ2rsC1PDaA1ojfiwa z*(=gybWm~9Xgs3aRyhW zJT#?N(gW=)*bU@kfNJb+S zY6_!i7zJbErmb~{`i2#dUPyg;s;g#NU9446Jx#=ml_@WOWfe&$M7w9rXzQj*3#L|G zY!%T;>Oq_kx4#g#Bt1pdI$Ad2I;ULS+tZh4E!%2Kr#t=8tYyda#S510BchSQ zCl($_rUw&|Xn$0Rq?050l{}IR4-V0IB1z+^SZvX-xNhja@NnPF;bBLQ-&tWYGX2S{ zWs4e(_a~ODWJ#(tOAJT%MB~dAK3}B;TvD`GGXeo+BDBk_ibA84cwlYbnO~b~^=o~V ztGr}Y`o6@X^brZFwX0gSJd5|3(sKE#R4c#g;nq*SKbQ+YE~s5i zJK;ey9+VG;+`%z#!0pY1g6?1@<9BB!4|+3WW75HK$?q|}{lvMCv##u;yqG^D)B_J> z_k_1ca(ksr(0won&*|XA`1rw~&+nTEPRNBbP~!t20ijL^`cvV%+P@{AxuHYlHt^PO`T!eZQws&F~hty z_^DvE`rpt(I%*In3J1FQ`MK~jyt*-OsF>EWS!}F``|qB-pN@|mouHW`N9p+SdygHt zYw~EFz5DQy@iFz-9Y^lIx4U?4$g;cS+9<96#*(v!&gzMcm#m!wRfW=m(lvz^m)-pJ zBelDQ7Q{iK`T2&6e->&DLPa444G-FirNO!m9k1VcodpmOHe%PS{oRK!LiiNHnEZm% zS&w~!C_>jMvYC05hjHSx38pDGy+JiO^;cc`H%0x^UHb3P;g$ZjA+!dtGt#)J8mBWt zg(9BQ7UW{21r3b0=rks$TTmw>Tj(9|fL4LT!3Rn)a>wo@puCF?XJ_;iVrJ~{y);Bz z)I}_e1W|M}2sGbLtc*01Jzi1jpiQWO>6@sVw9|I7iIFBWNSjXlp0u^vNh2d$i6ZZ4 zwX>RsiJjU>6C;ij4-an^REK>S+lBa2AIL|Cm zhR!1wJ&%s&x??$fdqWk_W&FwPc9f>usc2Z@TKanSYR++pqlrWDD^KS1|HuhfFmUK$ zbPsDhoNI9~+uL#G$E>T>vtD_3(h z-`8oV(-yu=ktb)kAH~{YI*n@>vLipMv2y@1ta*pM3&r4Tq48vn|25NhF4R7WjZQs5 zv-q#z6SDJ1Jbh)>^08`kas*Eitk>rkztzqY3ndmZMasJ3L`hf77fd<*mpBPOsl`AS z@Hvh^1X`EnG+3N|Yu3_MlkQ6l?N9sC()1r@Eq`hTO?qArTH%C?`13`@YrFKDOE;in6+rY`~bZ^nybbK2NT%Q`gLbS=4El(1-d zQL~({$XI(p-8?Sj!IBsIl4kpIWyE^TSkEusSM2I7kGFz z#j#4o>Pk#*SSeW?^=w4s2@iImg1#=0_PnO=MQwK$0Kc;F|{1d45lTnE951BZ0o&E6pF7C*|v7w)OS*Il}fyeZ0og;w#9dutM{VD zl4g``AK;+XWM}}(UZxu`NK4%%qXQf?jtmbV8AfW$TE)U_Bu;BP{t}p{LH7UM|2hZn Gcl;YI>bQ3R