From bde2cbfc7ad8a6dafd7230dc21f2dc751a94740f Mon Sep 17 00:00:00 2001 From: artemik Date: Mon, 11 Jul 2016 16:10:13 +0400 Subject: [PATCH 1/5] beacon java simplify --- beacon-java-rest/pom.xml | 57 ++-- .../providers/BeaconExceptionHandler.java | 87 ------ .../BeaconApplication.java | 2 +- .../rest/{api => endpoints}/BeaconInfo.java | 12 +- .../rest/{api => endpoints}/BeaconQuery.java | 18 +- .../{ => endpoints}/impl/BeaconInfoImpl.java | 20 +- .../rest/endpoints/impl/BeaconQueryImpl.java | 110 +++++++ .../rest/exceptions/BeaconException.java | 16 + .../InvalidAlleleRequestException.java | 29 ++ .../beacon/rest/impl/BeaconQueryImpl.java | 66 ---- .../rest/sys/BeaconExceptionHandler.java | 60 ++++ .../sys}/DefaultExceptionHandler.java | 26 +- .../sys}/GsonMessageBodyHandler.java | 72 ++--- .../beacon/util/ResponseMappingResource.java | 62 ---- .../com/dnastack/beacon/rest/BeaconTests.java | 292 +++++++++--------- .../src/test/resources/arquillian.xml | 16 +- beacon-java-service/pom.xml | 78 ----- .../beacon/service/api/BeaconService.java | 75 ----- .../service/impl/BeaconServiceImpl.java | 129 -------- .../src/main/resources/META-INF/beans.xml | 5 - pom.xml | 24 +- .../adapter/impl/SampleBeaconAdapterImpl.java | 217 ------------- .../core/adapter/impl/SampleDataStore.java | 58 ---- .../pom.xml | 21 +- .../beacon/core/service/BeaconService.java | 15 + .../service/impl/SampleBeaconServiceImpl.java | 156 ++++++++++ .../beacon/core/service/impl/SampleData.java | 123 ++++++++ 27 files changed, 780 insertions(+), 1066 deletions(-) delete mode 100644 beacon-java-rest/src/main/java/com/dnastack/beacon/providers/BeaconExceptionHandler.java rename beacon-java-rest/src/main/java/com/dnastack/beacon/{application => rest}/BeaconApplication.java (97%) rename beacon-java-rest/src/main/java/com/dnastack/beacon/rest/{api => endpoints}/BeaconInfo.java (87%) rename beacon-java-rest/src/main/java/com/dnastack/beacon/rest/{api => endpoints}/BeaconQuery.java (78%) rename beacon-java-rest/src/main/java/com/dnastack/beacon/rest/{ => endpoints}/impl/BeaconInfoImpl.java (76%) create mode 100644 beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconQueryImpl.java create mode 100644 beacon-java-rest/src/main/java/com/dnastack/beacon/rest/exceptions/BeaconException.java create mode 100644 beacon-java-rest/src/main/java/com/dnastack/beacon/rest/exceptions/InvalidAlleleRequestException.java delete mode 100644 beacon-java-rest/src/main/java/com/dnastack/beacon/rest/impl/BeaconQueryImpl.java create mode 100644 beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/BeaconExceptionHandler.java rename beacon-java-rest/src/main/java/com/dnastack/beacon/{providers => rest/sys}/DefaultExceptionHandler.java (73%) rename beacon-java-rest/src/main/java/com/dnastack/beacon/{providers => rest/sys}/GsonMessageBodyHandler.java (62%) delete mode 100644 beacon-java-rest/src/main/java/com/dnastack/beacon/util/ResponseMappingResource.java delete mode 100644 beacon-java-service/pom.xml delete mode 100644 beacon-java-service/src/main/java/com/dnastack/beacon/service/api/BeaconService.java delete mode 100644 beacon-java-service/src/main/java/com/dnastack/beacon/service/impl/BeaconServiceImpl.java delete mode 100644 beacon-java-service/src/main/resources/META-INF/beans.xml delete mode 100644 sample-beacon-adapter/src/main/java/com/dnastack/beacon/core/adapter/impl/SampleBeaconAdapterImpl.java delete mode 100644 sample-beacon-adapter/src/main/java/com/dnastack/beacon/core/adapter/impl/SampleDataStore.java rename {sample-beacon-adapter => sample-beacon-service}/pom.xml (85%) create mode 100644 sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/BeaconService.java create mode 100644 sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleBeaconServiceImpl.java create mode 100644 sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleData.java diff --git a/beacon-java-rest/pom.xml b/beacon-java-rest/pom.xml index 1bf0fea..534828e 100644 --- a/beacon-java-rest/pom.xml +++ b/beacon-java-rest/pom.xml @@ -9,13 +9,11 @@ 1.0-SNAPSHOT - - com.dnastack beacon-java-rest 1.0-SNAPSHOT war - beacon-java-rest + Beacon Java Rest @@ -108,23 +106,14 @@ rest-assured test - - com.dnastack - beacon-java-core - ${project.version} - - - com.dnastack - beacon-adapter-api - - + com.dnastack - sample-beacon-adapter + sample-beacon-service ${project.version} - + @@ -160,16 +149,12 @@ + org.apache.maven.plugins maven-surefire-plugin - ${version.surefire.plugin} true - - org.wildfly.plugins - wildfly-maven-plugin - @@ -181,17 +166,36 @@ wildfly-arquillian-container-managed test - - org.jboss.arquillian.protocol - arquillian-protocol-servlet - test - + + org.apache.maven.plugins + maven-dependency-plugin + + + unpack + process-test-classes + + unpack + + + + + org.wildfly + wildfly-dist + ${version.org.wildfly} + zip + false + ${project.build.directory} + + + + + + maven-surefire-plugin - ${version.surefire.plugin} false @@ -220,7 +224,6 @@ maven-surefire-plugin - ${version.surefire.plugin} false diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/providers/BeaconExceptionHandler.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/providers/BeaconExceptionHandler.java deleted file mode 100644 index 6d98a3a..0000000 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/providers/BeaconExceptionHandler.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * The MIT License - * - * Copyright 2014 Miroslav Cupak (mirocupak@gmail.com). - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.dnastack.beacon.providers; - -import com.dnastack.beacon.exceptions.BeaconAlleleRequestException; -import com.dnastack.beacon.exceptions.BeaconException; -import com.dnastack.beacon.service.api.BeaconService; -import org.ga4gh.beacon.Beacon; -import org.ga4gh.beacon.BeaconAlleleResponse; -import org.ga4gh.beacon.BeaconError; - -import javax.inject.Inject; -import javax.ws.rs.core.Response; -import javax.ws.rs.ext.ExceptionMapper; -import javax.ws.rs.ext.Provider; - -/** - * Beacon exceptions handler for catching beacon errors and returning the appropriate object - * - * @author patmagee - */ -@Provider -public class BeaconExceptionHandler implements ExceptionMapper { - - @Inject - BeaconService service; - - @Override - public Response toResponse(BeaconException exception) { - - BeaconError error = new BeaconError(); - error.setMessage(exception.getMessage()); - switch (exception.getReason()) { - case INVALID_REQUEST: - error.setErrorCode(Response.Status.BAD_REQUEST.getStatusCode()); - break; - default: - error.setErrorCode(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); - } - - //If this is an alleleRequest then return a BeaconAlleleResponse with the error fields set appropriately - if (exception.getClass().getCanonicalName().equals(BeaconAlleleRequestException.class.getCanonicalName())) { - BeaconAlleleRequestException e = (BeaconAlleleRequestException) exception; - BeaconAlleleResponse response = new BeaconAlleleResponse(); - response.setExists(null); - response.setError(error); - - if (e.getRequest() != null) { - response.setAlleleRequest(e.getRequest()); - } - - try { - Beacon beacon = service.queryBeacon(); - response.setBeaconId(beacon.getId()); - } catch (BeaconException ex) { - response.setBeaconId(null); - } - - return Response.status(error.getErrorCode()).entity(response).build(); - - } else { - BeaconError response = error; - return Response.status(error.getErrorCode()).entity(error).build(); - } - } -} diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/application/BeaconApplication.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/BeaconApplication.java similarity index 97% rename from beacon-java-rest/src/main/java/com/dnastack/beacon/application/BeaconApplication.java rename to beacon-java-rest/src/main/java/com/dnastack/beacon/rest/BeaconApplication.java index 39db57e..0829cef 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/application/BeaconApplication.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/BeaconApplication.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.dnastack.beacon.application; +package com.dnastack.beacon.rest; import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/api/BeaconInfo.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconInfo.java similarity index 87% rename from beacon-java-rest/src/main/java/com/dnastack/beacon/rest/api/BeaconInfo.java rename to beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconInfo.java index 08224d5..b2b457b 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/api/BeaconInfo.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconInfo.java @@ -21,9 +21,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.dnastack.beacon.rest.api; +package com.dnastack.beacon.rest.endpoints; -import com.dnastack.beacon.exceptions.BeaconException; +import com.dnastack.beacon.rest.exceptions.BeaconException; import org.ga4gh.beacon.Beacon; import javax.ws.rs.GET; @@ -32,20 +32,16 @@ import javax.ws.rs.core.MediaType; /** - * Beacon rest resource. - * * @author Miroslav Cupak (mirocupak@gmail.com) * @author Patrick Magee (patrickmageee@gmail.com) + * @author Artem (tema.voskoboynick@gmail.com) * @version 1.0 */ @Path("/") public interface BeaconInfo { /** - * Gets Information on the beacon - * - * @return Beacon represenation - * @throws BeaconException + * Gets information on the beacon. */ @GET @Produces({MediaType.APPLICATION_JSON}) diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/api/BeaconQuery.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconQuery.java similarity index 78% rename from beacon-java-rest/src/main/java/com/dnastack/beacon/rest/api/BeaconQuery.java rename to beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconQuery.java index 99333bd..45c2e83 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/api/BeaconQuery.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconQuery.java @@ -21,9 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.dnastack.beacon.rest.api; +package com.dnastack.beacon.rest.endpoints; -import com.dnastack.beacon.exceptions.BeaconException; +import com.dnastack.beacon.rest.exceptions.BeaconException; +import com.dnastack.beacon.rest.exceptions.InvalidAlleleRequestException; import org.ga4gh.beacon.BeaconAlleleRequest; import org.ga4gh.beacon.BeaconAlleleResponse; @@ -36,6 +37,7 @@ * * @author Miroslav Cupak (mirocupak@gmail.com) * @author Patrick Magee (patrickmageee@gmail.com) + * @author Artem (tema.voskoboynick@gmail.com) * @version 1.0 */ @Path("/query") @@ -58,7 +60,13 @@ public interface BeaconQuery { */ @GET @Produces({MediaType.APPLICATION_JSON}) - BeaconAlleleResponse query(@QueryParam("referenceName") String referenceName, @QueryParam("start") Long start, @QueryParam("referenceBases") String referenceBases, @QueryParam("alternateBases") String alternateBases, @QueryParam("assemblyId") String assemblyId, @QueryParam("datasetIds") List datasetIds, @QueryParam("includeDatasetResponses") Boolean includeDatasetResponses) throws BeaconException; + BeaconAlleleResponse query(@QueryParam("referenceName") String referenceName, + @QueryParam("start") Long start, + @QueryParam("referenceBases") String referenceBases, + @QueryParam("alternateBases") String alternateBases, + @QueryParam("assemblyId") String assemblyId, + @QueryParam("datasetIds") List datasetIds, + @QueryParam("includeDatasetResponses") Boolean includeDatasetResponses) throws InvalidAlleleRequestException; /** * Query a beacon resource for information on whether an allele exists or not. Optionally includes the datasets. @@ -66,12 +74,10 @@ public interface BeaconQuery { * was encountered. * * @param request Completed Beacon response object - * @return - * @throws BeaconException */ @POST @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) - BeaconAlleleResponse query(BeaconAlleleRequest request) throws BeaconException; + BeaconAlleleResponse query(BeaconAlleleRequest request) throws InvalidAlleleRequestException; } diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/impl/BeaconInfoImpl.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconInfoImpl.java similarity index 76% rename from beacon-java-rest/src/main/java/com/dnastack/beacon/rest/impl/BeaconInfoImpl.java rename to beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconInfoImpl.java index 1536a9d..e5204d9 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/impl/BeaconInfoImpl.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconInfoImpl.java @@ -21,18 +21,21 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.dnastack.beacon.rest.impl; +package com.dnastack.beacon.rest.endpoints.impl; -import com.dnastack.beacon.exceptions.BeaconException; -import com.dnastack.beacon.rest.api.BeaconInfo; -import com.dnastack.beacon.service.api.BeaconService; +import com.dnastack.beacon.core.service.BeaconService; +import com.dnastack.beacon.rest.endpoints.BeaconInfo; +import com.dnastack.beacon.rest.exceptions.BeaconException; import org.ga4gh.beacon.Beacon; import javax.inject.Inject; +import javax.ws.rs.GET; import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; /** - * Beacon Info Implementation + * @author Artem (tema.voskoboynick@gmail.com) */ @Path("/") public class BeaconInfoImpl implements BeaconInfo { @@ -40,11 +43,10 @@ public class BeaconInfoImpl implements BeaconInfo { @Inject private BeaconService service; - /** - * {@inheritDoc} - */ + @GET @Override + @Produces({MediaType.APPLICATION_JSON}) public Beacon info() throws BeaconException { - return service.queryBeacon(); + return service.getBeacon(); } } diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconQueryImpl.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconQueryImpl.java new file mode 100644 index 0000000..dc18202 --- /dev/null +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconQueryImpl.java @@ -0,0 +1,110 @@ +/* + * The MIT License + * + * Copyright 2014 Miroslav Cupak (mirocupak@gmail.com). + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.dnastack.beacon.rest.endpoints.impl; + +import com.dnastack.beacon.core.service.BeaconService; +import com.dnastack.beacon.rest.endpoints.BeaconQuery; +import com.dnastack.beacon.rest.exceptions.InvalidAlleleRequestException; +import org.apache.commons.lang.BooleanUtils; +import org.apache.commons.lang.StringUtils; +import org.ga4gh.beacon.BeaconAlleleRequest; +import org.ga4gh.beacon.BeaconAlleleResponse; + +import javax.inject.Inject; +import javax.ws.rs.Path; +import java.util.List; + +/** + * @author Artem (tema.voskoboynick@gmail.com) + * @author Patrick Magee (patrickmageee@gmail.com) + */ +@Path("/query") +public class BeaconQueryImpl implements BeaconQuery { + + @Inject + private BeaconService service; + + @Override + public BeaconAlleleResponse query(String referenceName, Long start, String referenceBases, String alternateBases, + String assemblyId, List datasetIds, Boolean includeDatasetResponses) + throws InvalidAlleleRequestException { + validateRequest(referenceName, start, referenceBases, alternateBases, assemblyId); + BeaconAlleleRequest request = BeaconAlleleRequest.newBuilder() + .setReferenceName(referenceName) + .setStart(start) + .setReferenceBases(referenceBases) + .setAlternateBases(alternateBases) + .setAssemblyId(assemblyId) + .setDatasetIds(datasetIds) + .setIncludeDatasetResponses(BooleanUtils.isTrue(includeDatasetResponses)) + .build(); + + return service.getBeaconAlleleResponse(request); + } + + @Override + public BeaconAlleleResponse query(BeaconAlleleRequest request) throws InvalidAlleleRequestException { + validateRequest(request); + return service.getBeaconAlleleResponse(request); + } + + private void validateRequest(BeaconAlleleRequest request) throws InvalidAlleleRequestException { + throwIf(request == null, "Request can't be null", request); + try { + validateRequest(request.getReferenceName(), request.getStart(), request.getReferenceBases(), request.getAlternateBases(), request.getAssemblyId()); + } catch (InvalidAlleleRequestException e) { + e.setRequest(request); + throw e; + } + } + + /** + * Validate the beacon fields according to the 0.3.0 beacon specifications. + */ + private void validateRequest(String referenceName, Long start, String referenceBases, String alternateBases, String assemblyId) throws InvalidAlleleRequestException { + boolean isValidReferenceName = StringUtils.isNotBlank(referenceName); + boolean isValidStart = start != null && start >= 0; + boolean isValidReferenceBases = StringUtils.isNotBlank(referenceBases); + boolean isValidAlternateBases = StringUtils.isNotBlank(alternateBases); + boolean isValidAssemblyId = StringUtils.startsWith(assemblyId, "GRCh"); + + throwIf(!isValidReferenceName, "Reference name can't be null"); + throwIf(!isValidStart, "Start position can't be null, should be 0-based positive integer"); + throwIf(!isValidReferenceBases, "Reference bases can't be null"); + throwIf(!isValidAlternateBases, "Alternate bases can't be null"); + throwIf(!isValidAssemblyId, "Assembly ID can't be null, should start with GRCh"); + } + + private static void throwIf(boolean expression, String message) throws InvalidAlleleRequestException { + if (expression) { + throw new InvalidAlleleRequestException(message); + } + } + + private static void throwIf(boolean expression, String message, BeaconAlleleRequest request) throws InvalidAlleleRequestException { + if (expression) { + throw new InvalidAlleleRequestException(request, message); + } + } +} diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/exceptions/BeaconException.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/exceptions/BeaconException.java new file mode 100644 index 0000000..f9424dc --- /dev/null +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/exceptions/BeaconException.java @@ -0,0 +1,16 @@ +package com.dnastack.beacon.rest.exceptions; + +/** + * @author Artem (tema.voskoboynick@gmail.com) + * @version 1.0 + */ +public class BeaconException extends Exception { + + public BeaconException() { + super(); + } + + public BeaconException(String message) { + super(message); + } +} diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/exceptions/InvalidAlleleRequestException.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/exceptions/InvalidAlleleRequestException.java new file mode 100644 index 0000000..63405ad --- /dev/null +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/exceptions/InvalidAlleleRequestException.java @@ -0,0 +1,29 @@ +package com.dnastack.beacon.rest.exceptions; + +import org.ga4gh.beacon.BeaconAlleleRequest; + +/** + * @author Artem (tema.voskoboynick@gmail.com) + * @version 1.0 + */ +public class InvalidAlleleRequestException extends BeaconException { + + private BeaconAlleleRequest request; + + public InvalidAlleleRequestException(String message) { + super(message); + } + + public InvalidAlleleRequestException(BeaconAlleleRequest request, String message) { + super(message); + this.request = request; + } + + public void setRequest(BeaconAlleleRequest request) { + this.request = request; + } + + public BeaconAlleleRequest getRequest() { + return request; + } +} diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/impl/BeaconQueryImpl.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/impl/BeaconQueryImpl.java deleted file mode 100644 index ff62f8d..0000000 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/impl/BeaconQueryImpl.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * The MIT License - * - * Copyright 2014 Miroslav Cupak (mirocupak@gmail.com). - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.dnastack.beacon.rest.impl; - -import com.dnastack.beacon.exceptions.BeaconException; -import com.dnastack.beacon.rest.api.BeaconQuery; -import com.dnastack.beacon.service.api.BeaconService; -import org.ga4gh.beacon.BeaconAlleleRequest; -import org.ga4gh.beacon.BeaconAlleleResponse; - -import javax.inject.Inject; -import javax.ws.rs.Path; -import java.util.List; - -/** - * Beacon Query Implementation - */ -@Path("/query") -public class BeaconQueryImpl implements BeaconQuery { - - @Inject - private BeaconService service; - - /** - * {@inheritDoc} - */ - @Override - public BeaconAlleleResponse query(String referenceName, Long start, String referenceBases, String alternateBases, String assemblyId, List datasetIds, Boolean includeDatasetResponses) throws BeaconException { - return service.queryAllele(referenceName, - start, - referenceBases, - alternateBases, - assemblyId, - datasetIds, - includeDatasetResponses); - } - - /** - * {@inheritDoc} - */ - @Override - public BeaconAlleleResponse query(BeaconAlleleRequest request) throws BeaconException { - return service.queryAllele(request); - } -} diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/BeaconExceptionHandler.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/BeaconExceptionHandler.java new file mode 100644 index 0000000..b829359 --- /dev/null +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/BeaconExceptionHandler.java @@ -0,0 +1,60 @@ +package com.dnastack.beacon.rest.sys; + +import com.dnastack.beacon.rest.exceptions.BeaconException; +import com.dnastack.beacon.rest.exceptions.InvalidAlleleRequestException; +import org.ga4gh.beacon.BeaconAlleleResponse; +import org.ga4gh.beacon.BeaconError; + +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +import static javax.ws.rs.core.Response.Status.BAD_REQUEST; +import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; + +/** + * @author patmagee + * @author Artem (tema.voskoboynick@gmail.com) + * @version 1.0 + */ +@Provider +public class BeaconExceptionHandler implements ExceptionMapper { + + /** + * Default error handler to capture all errors and send the user a JSON response + * with the status code, reason, message and stacktrace of the error + * + * @return response with the status and error entity + */ + @Override + public Response toResponse(BeaconException exception) { + if (exception instanceof InvalidAlleleRequestException) { + return handleInvalidAlleleRequestException((InvalidAlleleRequestException) exception); + } else { + return handleDefaultBeaconException(exception); + } + } + + private Response handleInvalidAlleleRequestException(InvalidAlleleRequestException exception) { + BeaconAlleleResponse response = new BeaconAlleleResponse(); + response.setAlleleRequest(exception.getRequest()); + response.setExists(null); + + BeaconError error = BeaconError.newBuilder() + .setErrorCode(BAD_REQUEST.getStatusCode()) + .setMessage(exception.getMessage()) + .build(); + response.setError(error); + + return Response.status(error.getErrorCode()).entity(response).build(); + } + + private Response handleDefaultBeaconException(BeaconException exception) { + BeaconError response = BeaconError.newBuilder() + .setMessage(exception.getMessage()) + .setErrorCode(INTERNAL_SERVER_ERROR.getStatusCode()) + .build(); + + return Response.status(response.getErrorCode()).entity(response).build(); + } +} diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/providers/DefaultExceptionHandler.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/DefaultExceptionHandler.java similarity index 73% rename from beacon-java-rest/src/main/java/com/dnastack/beacon/providers/DefaultExceptionHandler.java rename to beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/DefaultExceptionHandler.java index 8baa181..ec00f4f 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/providers/DefaultExceptionHandler.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/DefaultExceptionHandler.java @@ -21,40 +21,38 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.dnastack.beacon.providers; +package com.dnastack.beacon.rest.sys; -import com.dnastack.beacon.util.ResponseMappingResource; import org.ga4gh.beacon.BeaconError; -import org.json.simple.JSONObject; -import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; +import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; + /** - * Default Exception handler to catch all Non Beacon exceptions thrown by the rest resources.z + * Default Exception handler to catch all Non Beacon exceptions thrown by the rest resources. * * @author patmagee + * @author Artem (tema.voskoboynick@gmail.com) */ @Provider -public class DefaultExceptionHandler implements ExceptionMapper { +public class DefaultExceptionHandler implements ExceptionMapper { /** * Default error handler to capture all errors and send the user a JSON response * with the status code, reason, message and stacktrace of the error * - * @param e exceptions * @return response with the status and error entity */ @Override - public Response toResponse(Exception e) { - JSONObject json = new JSONObject(); - Response.Status s = ResponseMappingResource.getStatus(e); + public Response toResponse(Throwable exception) { + BeaconError response = BeaconError.newBuilder() + .setMessage(exception.getMessage()) + .setErrorCode(INTERNAL_SERVER_ERROR.getStatusCode()) + .build(); - BeaconError error = new BeaconError(); - error.setMessage(e.getMessage()); - error.setErrorCode(s.getStatusCode()); - return Response.status(s).entity(error).type(MediaType.APPLICATION_JSON_TYPE).build(); + return Response.status(response.getErrorCode()).entity(response).build(); } } diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/providers/GsonMessageBodyHandler.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/GsonMessageBodyHandler.java similarity index 62% rename from beacon-java-rest/src/main/java/com/dnastack/beacon/providers/GsonMessageBodyHandler.java rename to beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/GsonMessageBodyHandler.java index d8bed74..81d3b94 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/providers/GsonMessageBodyHandler.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/GsonMessageBodyHandler.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.dnastack.beacon.providers; +package com.dnastack.beacon.rest.sys; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -37,11 +37,13 @@ import java.io.*; import java.lang.annotation.Annotation; import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; /** - * Gson Message Body Handler for serializing JSON data to and from auto generated Java classes + * Gson Message Body Handler for serializing JSON data to and from auto generated Java classes. * * @author patmagee + * @author Artem (tema.voskoboynick@gmail.com) * @version 1.0 */ @Provider @@ -49,16 +51,8 @@ @Consumes(MediaType.APPLICATION_JSON) public class GsonMessageBodyHandler implements MessageBodyReader, MessageBodyWriter { - private static final String UTF_8 = "UTF-8"; - - private Gson gson; - - private Gson getGson() { - if (gson == null) { - gson = new GsonBuilder().create(); - } - return gson; - } + private static final Gson GSON = new GsonBuilder().create(); + private static final int UNKNOWN_LENGTH = -1; @Override public boolean isReadable(Class aClass, Type type, Annotation[] annotations, MediaType mediaType) { @@ -66,20 +60,18 @@ public boolean isReadable(Class aClass, Type type, Annotation[] annotations, } @Override - public Object readFrom(Class aClass, Type type, Annotation[] annotations, MediaType mediaType, MultivaluedMap multivaluedMap, InputStream inputStream) throws IOException, WebApplicationException { - InputStreamReader streamReader = new InputStreamReader(inputStream, UTF_8); - try { - Type jsonType; - if (type == null) { - jsonType = aClass; - } else if (aClass.equals(type)) { - jsonType = aClass; - } else { - jsonType = type; - } - return getGson().fromJson(streamReader, jsonType); - } finally { - streamReader.close(); + public Object readFrom(Class aClass, Type type, Annotation[] annotations, MediaType mediaType, + MultivaluedMap multivaluedMap, InputStream inputStream) throws IOException, + WebApplicationException { + Type objectType; + if (type == null || aClass.equals(type)) { + objectType = aClass; + } else { + objectType = type; + } + + try (InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) { + return GSON.fromJson(reader, objectType); } } @@ -90,24 +82,22 @@ public boolean isWriteable(Class aClass, Type type, Annotation[] annotations, @Override public long getSize(Object o, Class aClass, Type type, Annotation[] annotations, MediaType mediaType) { - return -1; + return UNKNOWN_LENGTH; } @Override - public void writeTo(Object o, Class aClass, Type type, Annotation[] annotations, MediaType mediaType, MultivaluedMap multivaluedMap, OutputStream outputStream) throws IOException, WebApplicationException { - OutputStreamWriter writer = new OutputStreamWriter(outputStream, UTF_8); - try { - Type jsonType; - if (type == null) { - jsonType = aClass; - } else if (aClass.equals(type)) { - jsonType = aClass; - } else { - jsonType = type; - } - getGson().toJson(o, jsonType, writer); - } finally { - writer.close(); + public void writeTo(Object o, Class aClass, Type type, Annotation[] annotations, MediaType mediaType, + MultivaluedMap multivaluedMap, OutputStream outputStream) throws IOException, + WebApplicationException { + Type objectType; + if (type == null || aClass.equals(type)) { + objectType = aClass; + } else { + objectType = type; + } + + try (OutputStreamWriter writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8)) { + GSON.toJson(o, objectType, writer); } } } diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/util/ResponseMappingResource.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/util/ResponseMappingResource.java deleted file mode 100644 index 993529a..0000000 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/util/ResponseMappingResource.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * The MIT License - * - * Copyright 2014 Miroslav Cupak (mirocupak@gmail.com). - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.dnastack.beacon.util; - -import javax.persistence.NoResultException; -import javax.ws.rs.NotFoundException; -import javax.ws.rs.core.Response; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -/** - * Created by patrickmagee on 2016-06-16. - */ -public class ResponseMappingResource { - - private static final Map mapping; - - static { - Map map = new HashMap<>(); - map.put(NotFoundException.class.getCanonicalName(), Response.Status.NOT_FOUND); - map.put(NoResultException.class.getCanonicalName(), Response.Status.NOT_FOUND); - map.put(IllegalArgumentException.class.getCanonicalName(), Response.Status.BAD_REQUEST); - map.put(UnsupportedOperationException.class.getCanonicalName(), Response.Status.METHOD_NOT_ALLOWED); - map.put(SecurityException.class.getCanonicalName(), Response.Status.FORBIDDEN); - mapping = Collections.unmodifiableMap(map); - } - - /** - * Retrieves Response.Status from a given exceptions according to the static mapping. If the mapping does not contain - * the exceptions, INTERNAL_SERVER_ERROR is returned. - * - * @param ex exceptions - * @return response status - */ - public static Response.Status getStatus(Exception ex) { - Response.Status s = mapping.get(ex.getClass().getCanonicalName()); - - return (s == null) ? Response.Status.INTERNAL_SERVER_ERROR : s; - } -} diff --git a/beacon-java-rest/src/test/java/com/dnastack/beacon/rest/BeaconTests.java b/beacon-java-rest/src/test/java/com/dnastack/beacon/rest/BeaconTests.java index d5843d1..e10c9b8 100644 --- a/beacon-java-rest/src/test/java/com/dnastack/beacon/rest/BeaconTests.java +++ b/beacon-java-rest/src/test/java/com/dnastack/beacon/rest/BeaconTests.java @@ -45,6 +45,8 @@ import java.net.URL; import static com.jayway.restassured.RestAssured.given; +import static javax.ws.rs.core.Response.Status.BAD_REQUEST; +import static javax.ws.rs.core.Response.Status.OK; import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.not; @@ -52,6 +54,7 @@ * Test suite run in an arquillian container against a beacon implementation * * @author patrickmagee. + * @author Artem (tema.voskoboynick@gmail.com) */ @RunWith(Arquillian.class) @RunAsClient @@ -67,16 +70,16 @@ public class BeaconTests { @Override protected void starting(Description description) { - System.out.println("Starting test: " + description.getClassName() + " - " + description.getMethodName() + "()"); + System.out.println(String.format("Starting test: %s - %s()", description.getClassName(), description.getMethodName())); } }; @Deployment(testable = false) public static WebArchive createDeployment() { WebArchive war = ShrinkWrap.create(MavenImporter.class) - .loadPomFromFile("pom.xml") - .importBuildOutput() - .as(WebArchive.class); + .loadPomFromFile("pom.xml") + .importBuildOutput() + .as(WebArchive.class); System.out.println("WAR name: " + war.getName()); return war; } @@ -86,12 +89,11 @@ public static WebArchive createDeployment() { */ @Test public void testGetBeacon() { - Beacon beacon = given().accept(ContentType.JSON) - .get(baseUrl) - .then() - .extract() - .as(Beacon.class, ObjectMapperType.GSON); + .get(baseUrl) + .then() + .extract() + .as(Beacon.class, ObjectMapperType.GSON); assertThat(beacon.getName()).isNotNull(); assertThat(beacon.getApiVersion()).isEqualTo(API_VERSION); @@ -105,7 +107,8 @@ public void testGetBeacon() { */ @Test public void testPostBeaconNotSupported() { - given().accept(ContentType.JSON).post(baseUrl).then().assertThat().statusCode(not(200)); + given().accept(ContentType.JSON).post(baseUrl) + .then().assertThat().statusCode(not(OK.getStatusCode())); } @@ -114,7 +117,8 @@ public void testPostBeaconNotSupported() { */ @Test public void testDeleteBeaconNotSupported() { - given().accept(ContentType.JSON).delete(baseUrl).then().assertThat().statusCode(not(200)); + given().accept(ContentType.JSON).delete(baseUrl) + .then().assertThat().statusCode(not(OK.getStatusCode())); } /** @@ -122,7 +126,8 @@ public void testDeleteBeaconNotSupported() { */ @Test public void testPutBeaconNotSupported() { - given().accept(ContentType.JSON).put(baseUrl).then().assertThat().statusCode(not(200)); + given().accept(ContentType.JSON).put(baseUrl) + .then().assertThat().statusCode(not(OK.getStatusCode())); } /** @@ -131,66 +136,63 @@ public void testPutBeaconNotSupported() { */ @Test public void testGetAllele() throws InterruptedException { - Beacon beacon = given().accept(ContentType.JSON) - .get(baseUrl) - .then() - .extract() - .as(Beacon.class, ObjectMapperType.GSON); + .get(baseUrl) + .then() + .extract() + .as(Beacon.class, ObjectMapperType.GSON); BeaconAlleleRequest request = beacon.getSampleAlleleRequests().get(0); - BeaconAlleleResponse out = given().accept(ContentType.JSON) - .queryParam("referenceName", request.getReferenceName()) - .queryParam("start", request.getStart()) - .queryParam("referenceBases", request.getReferenceBases()) - .queryParam("alternateBases", request.getAlternateBases()) - .queryParam("assemblyId", request.getAssemblyId()) - .queryParam("datasetIds", request.getDatasetIds()) - .queryParam("includeDatasetResponses", request.getIncludeDatasetResponses()) - .get(baseUrl + "query") - .then() - .extract() - .as(BeaconAlleleResponse.class, ObjectMapperType.GSON); - - assertThat(out.getAlleleRequest()).isNotNull(); - assertThat(out.getExists()).isTrue(); + BeaconAlleleResponse response = given().accept(ContentType.JSON) + .queryParam("referenceName", request.getReferenceName()) + .queryParam("start", request.getStart()) + .queryParam("referenceBases", request.getReferenceBases()) + .queryParam("alternateBases", request.getAlternateBases()) + .queryParam("assemblyId", request.getAssemblyId()) + .queryParam("datasetIds", request.getDatasetIds()) + .queryParam("includeDatasetResponses", request.getIncludeDatasetResponses()) + .get(baseUrl + "query") + .then() + .extract() + .as(BeaconAlleleResponse.class, ObjectMapperType.GSON); + + assertThat(response.getAlleleRequest()).isNotNull(); + assertThat(response.getExists()).isTrue(); if (request.getIncludeDatasetResponses()) { - assertThat(out.getDatasetAlleleResponses()).isNotEmpty(); + assertThat(response.getDatasetAlleleResponses()).isNotEmpty(); } - assertThat(out.getBeaconId()).isEqualTo(beacon.getId()); - assertThat(out.getError()).isNull(); + assertThat(response.getBeaconId()).isEqualTo(beacon.getId()); + assertThat(response.getError()).isNull(); } /** - * Test to make sure that you can post a BeaconAlleleResponse from /query enpoint, and that it complies + * Test to make sure that you can post a BeaconAlleleResponse from /query endpoint, and that it complies * with the current beacon spec. Uses the sampleAlleleRequest provided by the beacon */ @Test public void testPostAllele() { - Beacon beacon = given().accept(ContentType.JSON) - .get(baseUrl) - .then() - .extract() - .as(Beacon.class, ObjectMapperType.GSON); + .get(baseUrl) + .then() + .extract() + .as(Beacon.class, ObjectMapperType.GSON); BeaconAlleleRequest request = beacon.getSampleAlleleRequests().get(0); - BeaconAlleleResponse out = given().contentType(ContentType.JSON) - .accept(ContentType.JSON) - .body(request, ObjectMapperType.GSON) - .post(baseUrl + "query") - .then() - .extract() - .as(BeaconAlleleResponse.class, ObjectMapperType.GSON); + BeaconAlleleResponse response = given().contentType(ContentType.JSON) + .accept(ContentType.JSON) + .body(request, ObjectMapperType.GSON) + .post(baseUrl + "query") + .then() + .extract() + .as(BeaconAlleleResponse.class, ObjectMapperType.GSON); - assertThat(out.getAlleleRequest()).isEqualByComparingTo(request); - assertThat(out.getExists()).isTrue(); + assertThat(response.getAlleleRequest()).isEqualByComparingTo(request); + assertThat(response.getExists()).isTrue(); if (request.getIncludeDatasetResponses()) { - assertThat(out.getDatasetAlleleResponses()).isNotEmpty(); + assertThat(response.getDatasetAlleleResponses()).isNotEmpty(); } - assertThat(out.getBeaconId()).isEqualTo(beacon.getId()); - assertThat(out.getError()).isNull(); - + assertThat(response.getBeaconId()).isEqualTo(beacon.getId()); + assertThat(response.getError()).isNull(); } /** @@ -198,7 +200,8 @@ public void testPostAllele() { */ @Test public void testDeleteAlleleNotSupported() { - given().delete(baseUrl + "query").then().assertThat().statusCode(not(200)); + given().delete(baseUrl + "query") + .then().assertThat().statusCode(not(OK.getStatusCode())); } /** @@ -206,7 +209,8 @@ public void testDeleteAlleleNotSupported() { */ @Test public void testPutAlleleNotSupported() { - given().put(baseUrl + "query").then().assertThat().statusCode(not(200)); + given().put(baseUrl + "query") + .then().assertThat().statusCode(not(OK.getStatusCode())); } /** @@ -214,26 +218,21 @@ public void testPutAlleleNotSupported() { */ @Test public void testPostInvalidRequest() { - Beacon beacon = given().accept(ContentType.JSON) - .get(baseUrl) - .then() - .extract() - .as(Beacon.class, ObjectMapperType.GSON); - BeaconAlleleRequest request = beacon.getSampleAlleleRequests().get(0); + BeaconAlleleRequest request = getSampleAlleleRequest(); request.setReferenceName(null); request.setReferenceBases(null); BeaconAlleleResponse out = given().accept(ContentType.JSON) - .contentType(ContentType.JSON) - .body(request, ObjectMapperType.GSON) - .post(baseUrl + "query") - .then() - .extract() - .as(BeaconAlleleResponse.class, ObjectMapperType.GSON); + .contentType(ContentType.JSON) + .body(request, ObjectMapperType.GSON) + .post(baseUrl + "query") + .then() + .extract() + .as(BeaconAlleleResponse.class, ObjectMapperType.GSON); assertThat(out.getExists()).isNull(); assertThat(out.getError()).isNotNull(); - assertThat(out.getError().getErrorCode()).isEqualTo(400); + assertThat(out.getError().getErrorCode()).isEqualTo(BAD_REQUEST.getStatusCode()); } /** @@ -241,27 +240,22 @@ public void testPostInvalidRequest() { */ @Test public void testGetAlleleWithMissingRequiredParams() { - Beacon beacon = given().accept(ContentType.JSON) - .get(baseUrl) - .then() - .extract() - .as(Beacon.class, ObjectMapperType.GSON); - BeaconAlleleRequest request = beacon.getSampleAlleleRequests().get(0); - - BeaconAlleleResponse out = given().accept(ContentType.JSON) - .queryParam("referenceBases", request.getReferenceBases()) - .queryParam("alternateBases", request.getAlternateBases()) - .queryParam("assemblyId", request.getAssemblyId()) - .queryParam("datasetIds", request.getDatasetIds()) - .queryParam("includeDatasetResponses", request.getIncludeDatasetResponses()) - .get(baseUrl + "query") - .then() - .extract() - .as(BeaconAlleleResponse.class, ObjectMapperType.GSON); - - assertThat(out.getExists()).isNull(); - assertThat(out.getError()).isNotNull(); - assertThat(out.getError().getErrorCode()).isEqualTo(400); + BeaconAlleleRequest request = getSampleAlleleRequest(); + + BeaconAlleleResponse response = given().accept(ContentType.JSON) + .queryParam("referenceBases", request.getReferenceBases()) + .queryParam("alternateBases", request.getAlternateBases()) + .queryParam("assemblyId", request.getAssemblyId()) + .queryParam("datasetIds", request.getDatasetIds()) + .queryParam("includeDatasetResponses", request.getIncludeDatasetResponses()) + .get(baseUrl + "query") + .then() + .extract() + .as(BeaconAlleleResponse.class, ObjectMapperType.GSON); + + assertThat(response.getExists()).isNull(); + assertThat(response.getError()).isNotNull(); + assertThat(response.getError().getErrorCode()).isEqualTo(BAD_REQUEST.getStatusCode()); } /** @@ -269,30 +263,24 @@ public void testGetAlleleWithMissingRequiredParams() { */ @Test public void testGetAlleleWithMissingOptionalParams() { - Beacon beacon = given().accept(ContentType.JSON) - .get(baseUrl) - .then() - .extract() - .as(Beacon.class, ObjectMapperType.GSON); - BeaconAlleleRequest request = beacon.getSampleAlleleRequests().get(0); + BeaconAlleleRequest request = getSampleAlleleRequest(); request.setIncludeDatasetResponses(false); - BeaconAlleleResponse out = given().accept(ContentType.JSON) - .queryParam("referenceName", request.getReferenceName()) - .queryParam("start", request.getStart()) - .queryParam("referenceBases", request.getReferenceBases()) - .queryParam("alternateBases", request.getAlternateBases()) - .queryParam("assemblyId", request.getAssemblyId()) - .queryParam("datasetIds", request.getDatasetIds()) - .get(baseUrl + "query") - .then() - .extract() - .as(BeaconAlleleResponse.class, ObjectMapperType.GSON); - - assertThat(out.getAlleleRequest()).isEqualByComparingTo(request); - assertThat(out.getExists()).isTrue(); - assertThat(out.getDatasetAlleleResponses()).isNullOrEmpty(); - + BeaconAlleleResponse response = given().accept(ContentType.JSON) + .queryParam("referenceName", request.getReferenceName()) + .queryParam("start", request.getStart()) + .queryParam("referenceBases", request.getReferenceBases()) + .queryParam("alternateBases", request.getAlternateBases()) + .queryParam("assemblyId", request.getAssemblyId()) + .queryParam("datasetIds", request.getDatasetIds()) + .get(baseUrl + "query") + .then() + .extract() + .as(BeaconAlleleResponse.class, ObjectMapperType.GSON); + + assertThat(response.getAlleleRequest()).isEqualByComparingTo(request); + assertThat(response.getExists()).isTrue(); + assertThat(response.getDatasetAlleleResponses()).isNullOrEmpty(); } /** @@ -300,30 +288,25 @@ public void testGetAlleleWithMissingOptionalParams() { */ @Test public void testGetAlleleWithDataSets() { - Beacon beacon = given().accept(ContentType.JSON) - .get(baseUrl) - .then() - .extract() - .as(Beacon.class, ObjectMapperType.GSON); - BeaconAlleleRequest request = beacon.getSampleAlleleRequests().get(0); - - BeaconAlleleResponse out = given().accept(ContentType.JSON) - .queryParam("referenceName", request.getReferenceName()) - .queryParam("start", request.getStart()) - .queryParam("referenceBases", request.getReferenceBases()) - .queryParam("alternateBases", request.getAlternateBases()) - .queryParam("assemblyId", request.getAssemblyId()) - .queryParam("datasetIds", request.getDatasetIds()) - .queryParam("includeDatasetResponses", request.getIncludeDatasetResponses()) - .get(baseUrl + "query") - .then() - .extract() - .as(BeaconAlleleResponse.class, ObjectMapperType.GSON); - assertThat(out.getAlleleRequest()).isEqualByComparingTo(request); - assertThat(out.getExists()).isTrue(); - assertThat(out.getDatasetAlleleResponses()).isNotNull(); - assertThat(out.getDatasetAlleleResponses()).isNotEmpty(); - + BeaconAlleleRequest request = getSampleAlleleRequest(); + + BeaconAlleleResponse response = given().accept(ContentType.JSON) + .queryParam("referenceName", request.getReferenceName()) + .queryParam("start", request.getStart()) + .queryParam("referenceBases", request.getReferenceBases()) + .queryParam("alternateBases", request.getAlternateBases()) + .queryParam("assemblyId", request.getAssemblyId()) + .queryParam("datasetIds", request.getDatasetIds()) + .queryParam("includeDatasetResponses", request.getIncludeDatasetResponses()) + .get(baseUrl + "query") + .then() + .extract() + .as(BeaconAlleleResponse.class, ObjectMapperType.GSON); + + assertThat(response.getAlleleRequest()).isEqualByComparingTo(request); + assertThat(response.getExists()).isTrue(); + assertThat(response.getDatasetAlleleResponses()).isNotNull(); + assertThat(response.getDatasetAlleleResponses()).isNotEmpty(); } /** @@ -331,26 +314,21 @@ public void testGetAlleleWithDataSets() { */ @Test public void testGetAlleleWithoutDatasets() { - Beacon beacon = given().accept(ContentType.JSON) - .get(baseUrl) - .then() - .extract() - .as(Beacon.class, ObjectMapperType.GSON); - BeaconAlleleRequest request = beacon.getSampleAlleleRequests().get(0); + BeaconAlleleRequest request = getSampleAlleleRequest(); request.setIncludeDatasetResponses(false); BeaconAlleleResponse out = given().accept(ContentType.JSON) - .queryParam("referenceName", request.getReferenceName()) - .queryParam("start", request.getStart()) - .queryParam("referenceBases", request.getReferenceBases()) - .queryParam("alternateBases", request.getAlternateBases()) - .queryParam("assemblyId", request.getAssemblyId()) - .queryParam("datasetIds", request.getDatasetIds()) - .queryParam("includeDatasetResponses", false) - .get(baseUrl + "query") - .then() - .extract() - .as(BeaconAlleleResponse.class, ObjectMapperType.GSON); + .queryParam("referenceName", request.getReferenceName()) + .queryParam("start", request.getStart()) + .queryParam("referenceBases", request.getReferenceBases()) + .queryParam("alternateBases", request.getAlternateBases()) + .queryParam("assemblyId", request.getAssemblyId()) + .queryParam("datasetIds", request.getDatasetIds()) + .queryParam("includeDatasetResponses", false) + .get(baseUrl + "query") + .then() + .extract() + .as(BeaconAlleleResponse.class, ObjectMapperType.GSON); assertThat(out.getAlleleRequest()).isEqualByComparingTo(request); assertThat(out.getExists()).isTrue(); @@ -358,4 +336,12 @@ public void testGetAlleleWithoutDatasets() { assertThat(out.getDatasetAlleleResponses()).isNullOrEmpty(); } + private BeaconAlleleRequest getSampleAlleleRequest() { + Beacon beacon = given().accept(ContentType.JSON) + .get(baseUrl) + .then() + .extract() + .as(Beacon.class, ObjectMapperType.GSON); + return beacon.getSampleAlleleRequests().get(0); + } } diff --git a/beacon-java-rest/src/test/resources/arquillian.xml b/beacon-java-rest/src/test/resources/arquillian.xml index aa7193d..60b7101 100644 --- a/beacon-java-rest/src/test/resources/arquillian.xml +++ b/beacon-java-rest/src/test/resources/arquillian.xml @@ -7,13 +7,15 @@ target/ - + + + target/wildfly-8.2.1.Final + + -Xnoagent -Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n + true + - diff --git a/beacon-java-service/pom.xml b/beacon-java-service/pom.xml deleted file mode 100644 index 228914a..0000000 --- a/beacon-java-service/pom.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - beacon-java - com.dnastack - 1.0-SNAPSHOT - - 4.0.0 - - beacon-java-core - - - - MIT License - http://www.opensource.org/licenses/mit-license.php - repo - - - - - - patmagee - Patrick Magee - patrickmageee@gmail.com - https://github.com/patmagee - - - - - - javax.enterprise - cdi-api - provided - - - javax - javaee-api - provided - - - org.jboss.spec.javax.annotation - jboss-annotations-api_1.2_spec - provided - - - org.jboss.resteasy - jaxrs-api - provided - - - org.ga4gh - beacon - ${version.beacon.api} - - - com.dnastack - beacon-adapter-api - - - - ${project.artifactId} - - - maven-jar-plugin - - - maven-compiler-plugin - - 1.8 - 1.8 - - - - - - \ No newline at end of file diff --git a/beacon-java-service/src/main/java/com/dnastack/beacon/service/api/BeaconService.java b/beacon-java-service/src/main/java/com/dnastack/beacon/service/api/BeaconService.java deleted file mode 100644 index 12e404d..0000000 --- a/beacon-java-service/src/main/java/com/dnastack/beacon/service/api/BeaconService.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * The MIT License - * - * Copyright 2014 Miroslav Cupak (mirocupak@gmail.com). - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.dnastack.beacon.service.api; - -import com.dnastack.beacon.exceptions.BeaconAlleleRequestException; -import com.dnastack.beacon.exceptions.BeaconException; -import org.apache.avro.AvroRemoteException; -import org.ga4gh.beacon.Beacon; -import org.ga4gh.beacon.BeaconAlleleRequest; -import org.ga4gh.beacon.BeaconAlleleResponse; - -import java.util.List; - -/** - * Beacon service abstract class - * - * @author Miroslav Cupak (mirocupak@gmail.com) - * @version 1.0 - */ -public interface BeaconService { - - /** - * Get a beacon allele response from a beacon allele request. - * - * @param referenceName Not null chromosome name - * @param start Not null start position - * @param referenceBases Not null reference bases - * @param alternateBases Not null - * @param assemblyId Not null assembly version prefixed with GRCh - * @param datasetIds Dataset Ids to search, if null search all - * @param includeDatasetResponses Include datasets in return. - * @return Beacon allele response - * @throws AvroRemoteException - */ - BeaconAlleleResponse queryAllele(String referenceName, Long start, String referenceBases, String alternateBases, String assemblyId, List datasetIds, Boolean includeDatasetResponses) throws BeaconException; - - /** - * Get a beacon allele response from the beacon, given a BeaconAlleleRequest - * - * @param request Not null request object - * @return - * @throws BeaconAlleleRequestException - */ - BeaconAlleleResponse queryAllele(BeaconAlleleRequest request) throws BeaconException; - - /** - * Get information for a single beacon. - * - * @return - * @throws BeaconException - */ - Beacon queryBeacon() throws BeaconException; - -} diff --git a/beacon-java-service/src/main/java/com/dnastack/beacon/service/impl/BeaconServiceImpl.java b/beacon-java-service/src/main/java/com/dnastack/beacon/service/impl/BeaconServiceImpl.java deleted file mode 100644 index 97cfe2c..0000000 --- a/beacon-java-service/src/main/java/com/dnastack/beacon/service/impl/BeaconServiceImpl.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * The MIT License - * - * Copyright 2014 Miroslav Cupak (mirocupak@gmail.com). - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.dnastack.beacon.service.impl; - -import com.dnastack.beacon.adapter.api.BeaconAdapter; -import com.dnastack.beacon.exceptions.BeaconAlleleRequestException; -import com.dnastack.beacon.exceptions.BeaconException; -import com.dnastack.beacon.service.api.BeaconService; -import com.dnastack.beacon.utils.Reason; -import org.ga4gh.beacon.Beacon; -import org.ga4gh.beacon.BeaconAlleleRequest; -import org.ga4gh.beacon.BeaconAlleleResponse; - -import javax.enterprise.context.RequestScoped; -import javax.inject.Inject; -import java.util.List; - -/** - * Beacon service implementation. Ensures the request are valid, and throws the appropriate exceptions - * - * @author patrickmagee - */ -@RequestScoped -public class BeaconServiceImpl implements BeaconService { - - @Inject - private BeaconAdapter adapter; - - /** - * Validate the beacon fields according to the 0.3.0 beacon specifications - * - * @param referenceName - * @param start - * @param referenceBases - * @param alternateBases - * @param assemblyId - * @throws BeaconAlleleRequestException - */ - private void validateRequest(String referenceName, Long start, String referenceBases, String alternateBases, String assemblyId) throws BeaconAlleleRequestException { - if (referenceName == null) { - throw new BeaconAlleleRequestException(Reason.INVALID_REQUEST, - "Reference cannot be null. Please provide an appropriate reference name"); - } else if (start == null) { - throw new BeaconAlleleRequestException(Reason.INVALID_REQUEST, - "Start position cannot be null. Please provide a 0-based start position"); - } else if (referenceBases == null) { - throw new BeaconAlleleRequestException(Reason.INVALID_REQUEST, "Reference bases cannot be null"); - } else if (alternateBases == null) { - throw new BeaconAlleleRequestException(Reason.INVALID_REQUEST, "Alternate bases cannot be null"); - } else if (assemblyId == null) { - throw new BeaconAlleleRequestException(Reason.INVALID_REQUEST, - "AssemblyId cannot be null. Please defined a valid GRCh assembly Id"); - } else if (!assemblyId.startsWith("GRCh")) { - throw new BeaconAlleleRequestException(Reason.INVALID_REQUEST, - "Invalid assemblyId. Assemblies must be from GRCh builds"); - } - } - - /** - * @inheritDoc - **/ - @Override - public BeaconAlleleResponse queryAllele(String referenceName, Long start, String referenceBases, String alternateBases, String assemblyId, List datasetIds, Boolean includeDatasetResponses) throws BeaconException { - - validateRequest(referenceName, start, referenceBases, alternateBases, assemblyId); - - if (includeDatasetResponses == null) { - includeDatasetResponses = false; - } - - BeaconAlleleRequest request = new BeaconAlleleRequest(); - request.setReferenceName(referenceName); - request.setReferenceBases(referenceBases); - request.setAlternateBases(alternateBases); - request.setStart(start); - request.setIncludeDatasetResponses(includeDatasetResponses); - request.setAssemblyId(assemblyId); - request.setDatasetIds(datasetIds); - - return adapter.getBeaconAlleleResponse(request); - } - - /** - * @inheritDoc - **/ - @Override - public BeaconAlleleResponse queryAllele(BeaconAlleleRequest request) throws BeaconException { - validateRequest(request.getReferenceName(), - request.getStart(), - request.getReferenceBases(), - request.getAlternateBases(), - request.getAssemblyId()); - - if (request.getIncludeDatasetResponses() == null) { - request.setIncludeDatasetResponses(false); - } - - return adapter.getBeaconAlleleResponse(request); - } - - /** - * @inheritDoc - **/ - @Override - public Beacon queryBeacon() throws BeaconException { - return adapter.getBeacon(); - } -} diff --git a/beacon-java-service/src/main/resources/META-INF/beans.xml b/beacon-java-service/src/main/resources/META-INF/beans.xml deleted file mode 100644 index 28f1f92..0000000 --- a/beacon-java-service/src/main/resources/META-INF/beans.xml +++ /dev/null @@ -1,5 +0,0 @@ - - \ No newline at end of file diff --git a/pom.xml b/pom.xml index 14fa9a0..ce185ea 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,6 @@ beacon-java - beacon-java-service sample-beacon-adapter beacon-java-rest @@ -65,6 +64,7 @@ 1.1.1 3.4.1 1.0-SNAPSHOT + 8.2.1.Final @@ -110,7 +110,7 @@ org.assertj assertj-core - 3.4.1 + ${version.assertj} org.ga4gh @@ -120,7 +120,7 @@ com.googlecode.json-simple json-simple - 1.1.1 + ${version.json.simple} com.google.code.gson @@ -134,9 +134,16 @@ ${version.restassured} - com.dnastack - beacon-adapter-api - 1.0-SNAPSHOT + org.wildfly + wildfly-arquillian-container-managed + ${version.org.wildfly} + test + + + org.wildfly + wildfly-arquillian-container-remote + ${version.org.wildfly} + test @@ -158,6 +165,11 @@ wildfly-maven-plugin ${version.wildfly.maven.plugin} + + org.apache.maven.plugins + maven-surefire-plugin + ${version.surefire.plugin} + maven-compiler-plugin ${version.compiler.plugin} diff --git a/sample-beacon-adapter/src/main/java/com/dnastack/beacon/core/adapter/impl/SampleBeaconAdapterImpl.java b/sample-beacon-adapter/src/main/java/com/dnastack/beacon/core/adapter/impl/SampleBeaconAdapterImpl.java deleted file mode 100644 index e61133c..0000000 --- a/sample-beacon-adapter/src/main/java/com/dnastack/beacon/core/adapter/impl/SampleBeaconAdapterImpl.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * The MIT License - * - * Copyright 2014 Miroslav Cupak (mirocupak@gmail.com). - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.dnastack.beacon.core.adapter.impl; - -import com.dnastack.beacon.adapter.api.BeaconAdapter; -import com.dnastack.beacon.exceptions.BeaconException; -import org.ga4gh.beacon.*; - -import javax.annotation.PostConstruct; -import javax.enterprise.context.Dependent; -import java.util.*; - -/** - * Created by patrickmagee on 2016-06-17. - */ -@Dependent -public class SampleBeaconAdapterImpl implements BeaconAdapter { - - public static final String API_VERSION = "0.3.0"; - public static final String BEACON_ID = "beacon_id"; - public static final String DATASET_ID = "dataset_id"; - public static final String ORG_ID = "org_id"; - - private SampleDataStore dataStore; - - private BeaconDatasetAlleleResponse lookupDataset(String datasetId, String assemblyId, String referencName, long start, String refBases, String altBases) { - BeaconDatasetAlleleResponse response = new BeaconDatasetAlleleResponse(); - response.setDatasetId(datasetId); - - Map dataset = dataStore.getDATA().get(datasetId); - if (dataset == null) { - BeaconError be = new BeaconError(); - be.setErrorCode(404); - be.setMessage("Could not find dataset"); - - response.setExists(null); - response.setError(be); - - return response; - } - Map assembly = ((Map) dataset.get(assemblyId)); - if (assembly == null) { - BeaconError be = new BeaconError(); - be.setErrorCode(404); - be.setMessage("Could not find assembly in current dataset"); - - response.setExists(null); - response.setError(be); - - return response; - } - Map reference = ((Map) assembly.get(referencName)); - if (reference == null) { - response.setExists(null); - return addInfo(response); - } - Map bases = ((Map) reference.get(start)); - if (bases == null) { - response.setExists(false); - return addInfo(response); - } - if (bases.get("referenceBases").equals(refBases) && bases.get("alternateBases").equals(altBases)) { - response.setExists(true); - return addInfo(response); - } else { - response.setExists(false); - return addInfo(response); - } - } - - private BeaconDatasetAlleleResponse addInfo(BeaconDatasetAlleleResponse datasetResponse) { - datasetResponse.setCallCount(1l); - datasetResponse.setFrequency(0.221); - datasetResponse.setVariantCount(1l); - datasetResponse.setSampleCount(1l); - datasetResponse.setExternalUrl("www.google.com"); - datasetResponse.setNote("This is a sample beacon only"); - Map info = new HashMap<>(); - info.put("note", "Sample Beacon only"); - datasetResponse.setInfo(info); - return datasetResponse; - } - - private Beacon createSampleBeacon() { - Beacon beacon = new Beacon(); - beacon.setApiVersion(API_VERSION); - beacon.setVersion(API_VERSION); - beacon.setDescription("This is the description for a sample beacon"); - beacon.setName("Sample Beacon"); - beacon.setAlternativeUrl("www.google.ca"); - beacon.setWelcomeUrl("www.url"); - beacon.setDatasets(Arrays.asList(createSampleBeaconDataset())); - beacon.setCreateDateTime(new Date().toString()); - beacon.setUpdateDateTime(new Date().toString()); - beacon.setSampleAlleleRequests(Arrays.asList(createSampleRequest())); - beacon.setOrganization(createSampleOrganization()); - beacon.setId(BEACON_ID); - Map info = new HashMap<>(); - info.put("note", "Sample Beacon only"); - beacon.setInfo(info); - - return beacon; - } - - private BeaconAlleleRequest createSampleRequest() { - BeaconAlleleRequest request = new BeaconAlleleRequest(); - request.setDatasetIds(Arrays.asList(DATASET_ID)); - request.setReferenceName("1"); - request.setAssemblyId("GRCh37"); - request.setIncludeDatasetResponses(true); - request.setStart(1000l); - request.setReferenceBases("A"); - request.setAlternateBases("C"); - return request; - - } - - private BeaconOrganization createSampleOrganization() { - BeaconOrganization organization = new BeaconOrganization(); - organization.setAddress("123 Nullpointer Ave, StackTrace, Ohio"); - organization.setContactUrl("www.google.com"); - organization.setDescription("Sample implementation of a beacon organization"); - organization.setWelcomeUrl("www.google.com"); - organization.setLogoUrl("www.logoUrl.com"); - organization.setName("Sample Org"); - organization.setId(ORG_ID); - Map info = new HashMap<>(); - info.put("note", "Sample Beacon only"); - organization.setInfo(info); - - return organization; - } - - private BeaconDataset createSampleBeaconDataset() { - BeaconDataset dataset = new BeaconDataset(); - dataset.setName("Sample Dataset"); - dataset.setAssemblyId("GRCh37"); - dataset.setUpdateDateTime(new Date().toString()); - dataset.setCreateDateTime(new Date().toString()); - dataset.setId(DATASET_ID); - dataset.setVersion(API_VERSION); - dataset.setCallCount(10l); - dataset.setSampleCount(10l); - dataset.setDescription("Sample implementation"); - Map info = new HashMap<>(); - info.put("note", "Sample Beacon only"); - dataset.setInfo(info); - - return dataset; - - } - - @PostConstruct - public void init() { - dataStore = new SampleDataStore(); - } - - @Override - public BeaconAlleleResponse getBeaconAlleleResponse(BeaconAlleleRequest request) throws BeaconException { - - BeaconAlleleResponse response = new BeaconAlleleResponse(); - response.setBeaconId(BEACON_ID); - response.setAlleleRequest(request); - - List responses = new ArrayList<>(); - for (String datasetId : request.getDatasetIds()) { - responses.add(lookupDataset(datasetId, - request.getAssemblyId(), - request.getReferenceName(), - request.getStart(), - request.getReferenceBases(), - request.getAlternateBases())); - } - - if (!request.getIncludeDatasetResponses() && responses.size() == 1 && responses.get(0).getError() != null) { - response.setExists(null); - response.setError(responses.get(0).getError()); - } else if (request.getIncludeDatasetResponses()) { - response.setDatasetAlleleResponses(responses); - } - boolean exists = false; - for (BeaconDatasetAlleleResponse datasetResponses : responses) { - if (datasetResponses.getExists() == true) { - exists = true; - } - } - response.setExists(exists); - return response; - } - - @Override - public Beacon getBeacon() throws BeaconException { - return createSampleBeacon(); - } - -} diff --git a/sample-beacon-adapter/src/main/java/com/dnastack/beacon/core/adapter/impl/SampleDataStore.java b/sample-beacon-adapter/src/main/java/com/dnastack/beacon/core/adapter/impl/SampleDataStore.java deleted file mode 100644 index c7d2a83..0000000 --- a/sample-beacon-adapter/src/main/java/com/dnastack/beacon/core/adapter/impl/SampleDataStore.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * The MIT License - * - * Copyright 2014 Miroslav Cupak (mirocupak@gmail.com). - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.dnastack.beacon.core.adapter.impl; - -import java.util.HashMap; -import java.util.Map; - -/** - * This class simply is acting as a datastorage for the BeaconAdapter to perform lookups on - * - * @author patmagee - */ -public class SampleDataStore { - - private final Map DATA; - - public SampleDataStore() { - DATA = new HashMap<>(); - Map assemblies = new HashMap<>(); - Map references = new HashMap<>(); - Map positions = new HashMap<>(); - Map bases = new HashMap<>(); - bases.put("referenceBases", "A"); - bases.put("alternateBases", "C"); - positions.put(1000l, bases); - references.put("1", positions); - assemblies.put("GRCh37", references); - DATA.put(SampleBeaconAdapterImpl.DATASET_ID, assemblies); - - } - - public Map getDATA() { - return DATA; - } - -} diff --git a/sample-beacon-adapter/pom.xml b/sample-beacon-service/pom.xml similarity index 85% rename from sample-beacon-adapter/pom.xml rename to sample-beacon-service/pom.xml index da38128..d640585 100644 --- a/sample-beacon-adapter/pom.xml +++ b/sample-beacon-service/pom.xml @@ -26,16 +26,16 @@ + 4.0.0 + beacon-java com.dnastack 1.0-SNAPSHOT - 4.0.0 - sample-beacon-adapter - - jar + sample-beacon-service + Sample Beacon Adapter @@ -58,16 +58,6 @@ beacon ${version.beacon.api} - - com.dnastack - beacon-java-core - ${project.version} - - - com.dnastack - beacon-adapter-api - 1.0-SNAPSHOT - @@ -86,7 +76,4 @@ - sample-beacon-adapter - - \ No newline at end of file diff --git a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/BeaconService.java b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/BeaconService.java new file mode 100644 index 0000000..3c56f89 --- /dev/null +++ b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/BeaconService.java @@ -0,0 +1,15 @@ +package com.dnastack.beacon.core.service; + +import org.ga4gh.beacon.Beacon; +import org.ga4gh.beacon.BeaconAlleleRequest; +import org.ga4gh.beacon.BeaconAlleleResponse; + +/** + * @author Artem (tema.voskoboynick@gmail.com) + * @version 1.0 + */ +public interface BeaconService { + BeaconAlleleResponse getBeaconAlleleResponse(BeaconAlleleRequest request); + + Beacon getBeacon(); +} diff --git a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleBeaconServiceImpl.java b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleBeaconServiceImpl.java new file mode 100644 index 0000000..486399d --- /dev/null +++ b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleBeaconServiceImpl.java @@ -0,0 +1,156 @@ +/* + * The MIT License + * + * Copyright 2014 Miroslav Cupak (mirocupak@gmail.com). + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.dnastack.beacon.core.service.impl; + +import com.dnastack.beacon.core.service.BeaconService; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.BooleanUtils; +import org.ga4gh.beacon.*; + +import javax.enterprise.context.Dependent; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static javax.ws.rs.core.Response.Status; + +/** + * @author Artem (tema.voskoboynick@gmail.com) + * @author Patrick Magee (patrickmageee@gmail.com) + */ +@Dependent +public class SampleBeaconServiceImpl implements BeaconService { + + @Override + public Beacon getBeacon() { + return SampleData.BEACON; + } + + @Override + public BeaconAlleleResponse getBeaconAlleleResponse(BeaconAlleleRequest request) { + BeaconAlleleResponse response = new BeaconAlleleResponse(); + response.setBeaconId(SampleData.BEACON.getId()); + response.setAlleleRequest(request); + + DatasetsQueryResult datasetsResult = queryDatasets(request.getDatasetIds(), request.getAssemblyId(), + request.getReferenceName(), request.getStart(), request.getReferenceBases(), request.getAlternateBases()); + response.setExists(datasetsResult.exists); + if (BooleanUtils.isTrue(request.getIncludeDatasetResponses())) { + response.setDatasetAlleleResponses(datasetsResult.responses); + } + + return response; + } + + + private DatasetsQueryResult queryDatasets(List datasetIds, String assemblyId, String referenceName, Long start, + String referenceBases, String alternateBases) { + if (CollectionUtils.isEmpty(datasetIds)) { + // All datasets requested. + datasetIds = SampleData.DATASETS.keySet().stream().collect(Collectors.toList()); + } + + return doQueryDatasets(datasetIds, assemblyId, referenceName, start, referenceBases, alternateBases); + } + + private DatasetsQueryResult doQueryDatasets(List datasetIds, String assemblyId, String referenceName, Long start, + String referenceBases, String alternateBases) { + DatasetsQueryResult datasetsResult = new DatasetsQueryResult(); + + for (String datasetId : datasetIds) { + BeaconDatasetAlleleResponse datasetResponse = queryDataset(datasetId, assemblyId, referenceName, start, + referenceBases, alternateBases); + + // Find in descending priority: true, false, null. + Boolean existsInDataset = datasetResponse.getExists(); + if (datasetsResult.exists == null || BooleanUtils.isTrue(existsInDataset)) { + datasetsResult.exists = existsInDataset; + } + + // Collect any error, if exists. + if (datasetResponse.getError() != null) { + datasetsResult.error = datasetResponse.getError(); + } + + datasetsResult.responses.add(datasetResponse); + } + + return datasetsResult; + } + + @SuppressWarnings("unchecked") + private BeaconDatasetAlleleResponse queryDataset(String datasetId, String assemblyId, String referenceName, long start, String referenceBases, String alternateBases) { + Map dataset = SampleData.DATASETS.get(datasetId); + if (dataset == null) { + return createErrorDatasetResponse(datasetId, Status.NOT_FOUND.getStatusCode(), "Dataset not found"); + } + + Map assembly = dataset.get(assemblyId); + if (assembly == null) { + return createErrorDatasetResponse(datasetId, Status.NOT_FOUND.getStatusCode(), "Assembly not found"); + } + + Map reference = assembly.get(referenceName); + if (reference == null) { + return createErrorDatasetResponse(datasetId, Status.NOT_FOUND.getStatusCode(), "Reference not found"); + } + + Map bases = reference.get(start); + if (bases == null) { + return createSuccessfulDatasetResponse(datasetId, false); + } + + if (bases.get("referenceBases").equals(referenceBases) && bases.get("alternateBases").equals(alternateBases)) { + return createSuccessfulDatasetResponse(datasetId, true); + } else { + return createSuccessfulDatasetResponse(datasetId, false); + } + } + + private BeaconDatasetAlleleResponse createErrorDatasetResponse(String datasetId, int errorCode, String message) { + BeaconDatasetAlleleResponse response = new BeaconDatasetAlleleResponse(); + response.setDatasetId(datasetId); + + BeaconError error = BeaconError.newBuilder() + .setErrorCode(errorCode) + .setMessage(message).build(); + response.setError(error); + + return response; + } + + private BeaconDatasetAlleleResponse createSuccessfulDatasetResponse(String datasetId, boolean exists) { + BeaconDatasetAlleleResponse response = BeaconDatasetAlleleResponse.newBuilder(SampleData.BASE_DATASET_RESPONSE).build(); + response.setDatasetId(datasetId); + response.setExists(exists); + return response; + } + + private static class DatasetsQueryResult { + Boolean exists; + BeaconError error; + List responses = new ArrayList<>(); + } +} diff --git a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleData.java b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleData.java new file mode 100644 index 0000000..dfdee5d --- /dev/null +++ b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleData.java @@ -0,0 +1,123 @@ +/* + * The MIT License + * + * Copyright 2014 Miroslav Cupak (mirocupak@gmail.com). + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.dnastack.beacon.core.service.impl; + +import avro.shaded.com.google.common.collect.ImmutableMap; +import org.ga4gh.beacon.*; + +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * This class simply is acting as a datastorage for the BeaconAdapter to perform lookups on + * + * @author patmagee + * @author Artem (tema.voskoboynick@gmail.com) + */ +public class SampleData { + + public static final Map DATASETS; + public static final Beacon BEACON; + public static final BeaconDatasetAlleleResponse BASE_DATASET_RESPONSE; + + static { + BeaconDataset dataset = BeaconDataset.newBuilder() + .setName("Sample Dataset") + .setAssemblyId("GRCh37") + .setUpdateDateTime(new Date().toString()) + .setCreateDateTime(new Date().toString()) + .setId("sample_dataset_id") + .setVersion("0.3.0") + .setCallCount(10L) + .setSampleCount(10L) + .setDescription("Sample implementation") + .setInfo(ImmutableMap.of("note", "This is a Sample Dataset")) + .build(); + + BASE_DATASET_RESPONSE = BeaconDatasetAlleleResponse.newBuilder() + .setCallCount(1L) + .setFrequency(0.221) + .setVariantCount(1L) + .setSampleCount(1L) + .setExternalUrl("www.google.com") + .setInfo(ImmutableMap.of("Sample Note", "Sample Note Value")) + .setDatasetId(dataset.getId()) + .setExists(null) // Setting nulls explicitly required by avro. + .build(); + + BeaconAlleleRequest request = BeaconAlleleRequest.newBuilder() + .setDatasetIds(Collections.singletonList(dataset.getId())) + .setReferenceName("1") + .setAssemblyId("GRCh37") + .setIncludeDatasetResponses(true) + .setStart(1000L) + .setReferenceBases("A") + .setAlternateBases("C") + .build(); + + DATASETS = new HashMap() { + { + Map bases = ImmutableMap.of( + "referenceBases", request.getReferenceBases(), + "alternateBases", request.getAlternateBases() + ); + Map positions = ImmutableMap.of(request.getStart(), bases); + Map references = ImmutableMap.of(request.getReferenceName(), positions); + Map assemblies = ImmutableMap.of(request.getAssemblyId(), references); + + put(dataset.getId(), assemblies); + } + }; + + BeaconOrganization organization = BeaconOrganization.newBuilder() + .setAddress("123 Nullpointer Ave, StackTrace, Ohio") + .setContactUrl("www.google.com") + .setDescription("Sample implementation of a beacon organization") + .setWelcomeUrl("www.google.com") + .setLogoUrl("www.logoUrl.com") + .setName("Sample Organization") + .setId("sample_organization_id") + .setInfo(ImmutableMap.of("note", "This is a sample Organization")) + .build(); + + BEACON = Beacon.newBuilder() + .setApiVersion("0.3.0") + .setVersion("0.3.0") + .setDescription("Sample description") + .setName("Sample Beacon") + .setAlternativeUrl("www.google.ca") + .setWelcomeUrl("www.url") + .setDatasets(Collections.singletonList(dataset)) + .setCreateDateTime(new Date().toString()) + .setUpdateDateTime(new Date().toString()) + .setSampleAlleleRequests(Collections.singletonList(request)) + .setOrganization(organization) + .setId("sample_beacon_id") + .setInfo(ImmutableMap.of("note", "This is a sample Beacon")) + .build(); + } +} From 7f042ab9eee7ba2ef073d71da8c1253bd8d5e6c5 Mon Sep 17 00:00:00 2001 From: artemik Date: Mon, 11 Jul 2016 16:12:09 +0400 Subject: [PATCH 2/5] beacon java simplify 2 --- pom.xml | 2 +- sample-beacon-service/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ce185ea..819a310 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ beacon-java - sample-beacon-adapter + sample-beacon-service beacon-java-rest diff --git a/sample-beacon-service/pom.xml b/sample-beacon-service/pom.xml index d640585..c9fd09c 100644 --- a/sample-beacon-service/pom.xml +++ b/sample-beacon-service/pom.xml @@ -35,7 +35,7 @@ sample-beacon-service - Sample Beacon Adapter + Sample Beacon Service From 7e5eeb3234ebc41b56e6bb6eaa3359aa5bac2658 Mon Sep 17 00:00:00 2001 From: artemik Date: Mon, 11 Jul 2016 23:06:37 +0400 Subject: [PATCH 3/5] keycloak authz basic config --- beacon-java-rest/pom.xml | 18 +++++++++++++ .../beacon/rest/BeaconApplication.java | 2 ++ .../beacon/rest/endpoints/BeaconQuery.java | 5 +++- .../rest/endpoints/impl/BeaconInfoImpl.java | 2 ++ .../rest/endpoints/impl/BeaconQueryImpl.java | 11 +++++++- .../rest/sys/DefaultExceptionHandler.java | 4 ++- .../src/main/webapp/META-INF/beans.xml | 4 +++ .../src/main/webapp/WEB-INF/beans.xml | 9 +++++++ .../src/main/webapp/WEB-INF/keycloak.json | 11 ++++++++ .../src/main/webapp/WEB-INF/web.xml | 11 ++++++++ .../src/test/resources/arquillian.xml | 12 ++++----- .../service/impl/SampleBeaconServiceImpl.java | 6 +++++ .../beacon/core/service/impl/SampleData.java | 2 +- .../beacon/core/service/test/MyInterface.java | 9 +++++++ .../core/service/test/MyInterfaceImpl.java | 15 +++++++++++ .../service/test/MyInterrfaceSecondImpl.java | 26 +++++++++++++++++++ 16 files changed, 137 insertions(+), 10 deletions(-) create mode 100644 beacon-java-rest/src/main/webapp/WEB-INF/beans.xml create mode 100644 beacon-java-rest/src/main/webapp/WEB-INF/keycloak.json create mode 100644 sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterface.java create mode 100644 sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterfaceImpl.java create mode 100644 sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterrfaceSecondImpl.java diff --git a/beacon-java-rest/pom.xml b/beacon-java-rest/pom.xml index 534828e..8bf44eb 100644 --- a/beacon-java-rest/pom.xml +++ b/beacon-java-rest/pom.xml @@ -106,6 +106,21 @@ rest-assured test + + org.keycloak + keycloak-servlet-filter-adapter + 2.0.0.Final + + + org.keycloak + keycloak-authz-client + 2.0.0.Final + + + org.apache.httpcomponents + httpclient + 4.5.2 + @@ -129,6 +144,9 @@ org.wildfly.plugins wildfly-maven-plugin + + 10090 + maven-compiler-plugin diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/BeaconApplication.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/BeaconApplication.java index 0829cef..a11c139 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/BeaconApplication.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/BeaconApplication.java @@ -25,6 +25,8 @@ import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; +import java.util.HashSet; +import java.util.Set; /** * REST beacon application. diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconQuery.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconQuery.java index 45c2e83..de7b7d3 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconQuery.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconQuery.java @@ -28,7 +28,9 @@ import org.ga4gh.beacon.BeaconAlleleRequest; import org.ga4gh.beacon.BeaconAlleleResponse; +import javax.servlet.http.HttpServletRequest; import javax.ws.rs.*; +import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import java.util.List; @@ -66,7 +68,8 @@ BeaconAlleleResponse query(@QueryParam("referenceName") String referenceName, @QueryParam("alternateBases") String alternateBases, @QueryParam("assemblyId") String assemblyId, @QueryParam("datasetIds") List datasetIds, - @QueryParam("includeDatasetResponses") Boolean includeDatasetResponses) throws InvalidAlleleRequestException; + @QueryParam("includeDatasetResponses") Boolean includeDatasetResponses, + @Context HttpServletRequest servletRequest) throws InvalidAlleleRequestException; /** * Query a beacon resource for information on whether an allele exists or not. Optionally includes the datasets. diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconInfoImpl.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconInfoImpl.java index e5204d9..b9867cd 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconInfoImpl.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconInfoImpl.java @@ -27,6 +27,8 @@ import com.dnastack.beacon.rest.endpoints.BeaconInfo; import com.dnastack.beacon.rest.exceptions.BeaconException; import org.ga4gh.beacon.Beacon; +import org.keycloak.AuthorizationContext; +import org.keycloak.KeycloakSecurityContext; import javax.inject.Inject; import javax.ws.rs.GET; diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconQueryImpl.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconQueryImpl.java index dc18202..e7324ad 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconQueryImpl.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconQueryImpl.java @@ -30,9 +30,14 @@ import org.apache.commons.lang.StringUtils; import org.ga4gh.beacon.BeaconAlleleRequest; import org.ga4gh.beacon.BeaconAlleleResponse; +import org.keycloak.AuthorizationContext; +import org.keycloak.KeycloakSecurityContext; import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Path; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Request; import java.util.List; /** @@ -47,8 +52,12 @@ public class BeaconQueryImpl implements BeaconQuery { @Override public BeaconAlleleResponse query(String referenceName, Long start, String referenceBases, String alternateBases, - String assemblyId, List datasetIds, Boolean includeDatasetResponses) + String assemblyId, List datasetIds, Boolean includeDatasetResponses, @Context HttpServletRequest servletRequest) throws InvalidAlleleRequestException { + + KeycloakSecurityContext keycloakSecurityContext = (KeycloakSecurityContext) servletRequest.getAttribute(KeycloakSecurityContext.class.getName()); + AuthorizationContext authzContext = keycloakSecurityContext.getAuthorizationContext(); + validateRequest(referenceName, start, referenceBases, alternateBases, assemblyId); BeaconAlleleRequest request = BeaconAlleleRequest.newBuilder() .setReferenceName(referenceName) diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/DefaultExceptionHandler.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/DefaultExceptionHandler.java index ec00f4f..944343c 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/DefaultExceptionHandler.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/DefaultExceptionHandler.java @@ -25,6 +25,8 @@ import org.ga4gh.beacon.BeaconError; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; @@ -53,6 +55,6 @@ public Response toResponse(Throwable exception) { .setErrorCode(INTERNAL_SERVER_ERROR.getStatusCode()) .build(); - return Response.status(response.getErrorCode()).entity(response).build(); + return Response.status(response.getErrorCode()).type(MediaType.APPLICATION_JSON).entity(response).build(); } } diff --git a/beacon-java-rest/src/main/webapp/META-INF/beans.xml b/beacon-java-rest/src/main/webapp/META-INF/beans.xml index 28f1f92..f806c1b 100644 --- a/beacon-java-rest/src/main/webapp/META-INF/beans.xml +++ b/beacon-java-rest/src/main/webapp/META-INF/beans.xml @@ -1,5 +1,9 @@ + + com.dnastack.beacon.core.service.test.MyInterrfaceSecondImpl + \ No newline at end of file diff --git a/beacon-java-rest/src/main/webapp/WEB-INF/beans.xml b/beacon-java-rest/src/main/webapp/WEB-INF/beans.xml new file mode 100644 index 0000000..9517ba1 --- /dev/null +++ b/beacon-java-rest/src/main/webapp/WEB-INF/beans.xml @@ -0,0 +1,9 @@ + + + com.dnastack.beacon.core.service.test.MyInterrfaceSecondImpl + + \ No newline at end of file diff --git a/beacon-java-rest/src/main/webapp/WEB-INF/keycloak.json b/beacon-java-rest/src/main/webapp/WEB-INF/keycloak.json new file mode 100644 index 0000000..883a0c0 --- /dev/null +++ b/beacon-java-rest/src/main/webapp/WEB-INF/keycloak.json @@ -0,0 +1,11 @@ +{ + "realm": "beacon-realm", + "realm-public-key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsRX+fPYkN9fXgbRq9BCrVW8F2HrWUV4ss3bpeeT71n04uqD+v0Q9R9rfR3wG7uf/iB3PVASkmVS2Up7UwsuOZn2dmzyCRmom4O+oj6lzFWgSYuGwmY2rpmDg1m7apDR9cMODXI9D8Yqk7miGDo6+W10Xh9vA/IXH24OuuI4Mgs1mEoSZZC068YsRr9J0Dt58ttkr7PHCm7P2wqr5fDRhfY67q2w1lMW384GZxA7x0P7MGUebd1swPuQvZUyZuU/lVLca/lRX7D8g4gK9NYyUI/FBGUf4EPFVvYjmfmIvl3HWerkkZuL9U8Etr0WaOMig1sY4KWbQiaQtQVsV7V4ASQIDAQAB", + "auth-server-url": "http://localhost:8280/auth", + "ssl-required": "external", + "resource": "beacon-rest", + "credentials": { + "secret": "01d0bc41-1365-4922-b1ec-a241196735fa" + }, + "policy-enforcer": {} +} \ No newline at end of file diff --git a/beacon-java-rest/src/main/webapp/WEB-INF/web.xml b/beacon-java-rest/src/main/webapp/WEB-INF/web.xml index 94d318d..5fa8380 100644 --- a/beacon-java-rest/src/main/webapp/WEB-INF/web.xml +++ b/beacon-java-rest/src/main/webapp/WEB-INF/web.xml @@ -16,4 +16,15 @@ 30 + + + Keycloak Filter + org.keycloak.adapters.servlet.KeycloakOIDCFilter + + + Keycloak Filter + /keycloak/* + /protected/* + /query/* + diff --git a/beacon-java-rest/src/test/resources/arquillian.xml b/beacon-java-rest/src/test/resources/arquillian.xml index 60b7101..c45c19f 100644 --- a/beacon-java-rest/src/test/resources/arquillian.xml +++ b/beacon-java-rest/src/test/resources/arquillian.xml @@ -9,13 +9,13 @@ - target/wildfly-8.2.1.Final - - -Xnoagent -Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n true + target/wildfly-8.2.1.Final + + -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n + -Djboss.socket.binding.port-offset=100 + + 10090 - diff --git a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleBeaconServiceImpl.java b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleBeaconServiceImpl.java index 486399d..b2fbb94 100644 --- a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleBeaconServiceImpl.java +++ b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleBeaconServiceImpl.java @@ -24,11 +24,13 @@ package com.dnastack.beacon.core.service.impl; import com.dnastack.beacon.core.service.BeaconService; +import com.dnastack.beacon.core.service.test.MyInterface; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.BooleanUtils; import org.ga4gh.beacon.*; import javax.enterprise.context.Dependent; +import javax.inject.Inject; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -43,8 +45,12 @@ @Dependent public class SampleBeaconServiceImpl implements BeaconService { + @Inject + private MyInterface myInterface; + @Override public Beacon getBeacon() { + myInterface.hello(); return SampleData.BEACON; } diff --git a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleData.java b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleData.java index dfdee5d..cab54e5 100644 --- a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleData.java +++ b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleData.java @@ -46,11 +46,11 @@ public class SampleData { static { BeaconDataset dataset = BeaconDataset.newBuilder() + .setId("sample_dataset_id_1") .setName("Sample Dataset") .setAssemblyId("GRCh37") .setUpdateDateTime(new Date().toString()) .setCreateDateTime(new Date().toString()) - .setId("sample_dataset_id") .setVersion("0.3.0") .setCallCount(10L) .setSampleCount(10L) diff --git a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterface.java b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterface.java new file mode 100644 index 0000000..fe2bd5b --- /dev/null +++ b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterface.java @@ -0,0 +1,9 @@ +package com.dnastack.beacon.core.service.test; + +/** + * @author Artem (tema.voskoboynick@gmail.com) + * @version 1.0 + */ +public interface MyInterface { + void hello(); +} diff --git a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterfaceImpl.java b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterfaceImpl.java new file mode 100644 index 0000000..4994a22 --- /dev/null +++ b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterfaceImpl.java @@ -0,0 +1,15 @@ +package com.dnastack.beacon.core.service.test; + +import javax.enterprise.context.Dependent; + +/** + * @author Artem (tema.voskoboynick@gmail.com) + * @version 1.0 + */ +@Dependent +public class MyInterfaceImpl implements MyInterface { + @Override + public void hello() { + System.out.println("hello"); + } +} diff --git a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterrfaceSecondImpl.java b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterrfaceSecondImpl.java new file mode 100644 index 0000000..b368b6b --- /dev/null +++ b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterrfaceSecondImpl.java @@ -0,0 +1,26 @@ +package com.dnastack.beacon.core.service.test; + +import com.dnastack.beacon.core.service.BeaconService; + +import javax.decorator.Decorator; +import javax.decorator.Delegate; +import javax.enterprise.inject.Any; +import javax.inject.Inject; + +/** + * @author Artem (tema.voskoboynick@gmail.com) + * @version 1.0 + */ +@Decorator +public class MyInterrfaceSecondImpl implements MyInterface { + + @Inject + @Delegate + @Any + private MyInterface MyInterface; + + @Override + public void hello() { + System.out.println("hello EXTENDED"); + } +} From 5c2a3e4dc7962518062079b24c4d9d482f26ba5c Mon Sep 17 00:00:00 2001 From: artemik Date: Tue, 12 Jul 2016 15:32:44 +0400 Subject: [PATCH 4/5] added keycloak security --- README.md | 22 ++-- beacon-java-rest/pom.xml | 4 +- .../beacon/rest/BeaconApplication.java | 2 - .../beacon/rest/endpoints/BeaconQuery.java | 26 ++--- .../rest/endpoints/impl/BeaconInfoImpl.java | 2 - .../rest/endpoints/impl/BeaconQueryImpl.java | 9 +- .../impl/secured/SecuredBeaconQueryImpl.java | 105 ++++++++++++++++++ .../rest/exceptions/BeaconException.java | 2 + .../rest/sys/BeaconExceptionHandler.java | 12 +- .../rest/sys/DefaultExceptionHandler.java | 9 +- .../ConfigurableKeycloakOIDCFilter.java | 35 ++++++ .../rest/sys/security/SecurityContext.java | 19 ++++ .../src/main/webapp/META-INF/beans.xml | 9 -- .../src/main/webapp/WEB-INF/beans.xml | 5 +- .../src/main/webapp/WEB-INF/web.xml | 11 +- pom.xml | 17 +++ .../beacon/core/service/BeaconService.java | 2 + .../service/impl/SampleBeaconServiceImpl.java | 6 - .../beacon/core/service/impl/SampleData.java | 30 ++--- .../beacon/core/service/test/MyInterface.java | 9 -- .../core/service/test/MyInterfaceImpl.java | 15 --- .../service/test/MyInterrfaceSecondImpl.java | 26 ----- 22 files changed, 240 insertions(+), 137 deletions(-) create mode 100644 beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/secured/SecuredBeaconQueryImpl.java create mode 100644 beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/security/ConfigurableKeycloakOIDCFilter.java create mode 100644 beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/security/SecurityContext.java delete mode 100644 beacon-java-rest/src/main/webapp/META-INF/beans.xml delete mode 100644 sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterface.java delete mode 100644 sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterfaceImpl.java delete mode 100644 sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterrfaceSecondImpl.java diff --git a/README.md b/README.md index 15002cd..6aa63ee 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ ##What it is This project contains the BDK (beacon development kit) for Java (EE) developers. The BDK provides all of the tools required to create a basic rest implementation for a beacon almost straight out of the box with only minimal set up required. -Users can extend the BDK to make it fit within their own project, or use it as is defining their own adapter to retrieve data from their preferred data source. +Users can extend the BDK to make it fit within their own project, or use it as is defining their own service to retrieve data from their preferred data source. ##System requirements All you need to build this project is Java 8.0 (Java SDK 1.8) or later, Maven 3.0 or later. Since the project is Java EE based, an application server with support for Java EE 7 is needed to deploy the application (e.g. JBoss EAP or WildFly). @@ -38,10 +38,8 @@ mvn clean install ## How it Works The project provides the following: -- API for beacons -- sample beacon implementation -- conversion of parameters to a normalized form (the same way Beacon of Beacons does) -- sample navigation webpage +- Rest API +- sample beacon service implementation - sample test suite ##How to run it @@ -64,19 +62,17 @@ In order to run the tests from beacon-java-rest in a managed (remote) container, mvn test -Ptest-managed ##Creating a beacon -The beacon implementation is designed to use a beacon-adapter provided through the [beacon-adapter-api project](https://github.com/mcupak/beacon-adapter-api) project. The user can either extend the abstract BeaconAdapter class to create a custom implementation, or they can use one of the beacon-adapter implementations that are provided +Beacon REST API uses Beacon Service to retrieve the beacon data. The BDK ships with a sample Beacon Service that uses sample data. +The sample Beacon Service is intended to be a placeholder to allow the tests to be run, and to give the user an idea of how to implement a beacon. -Once you have created your own adapter, simply replace the adapter dependency in the beacon-java-rest's pom with your own. The sample beacon adapter is intended to be a placeholder to allow the tests to be run, and to give the user an idea of how to implement a beacon. After this has been completely they are free to implement their own adapter. +Once you are ready, implement your own [beacon-service](https://github.com/mcupak/beacon-service) project to use query own data. +To switch to your own Beacon Service, simply replace the service dependency in the beacon-java-rest's pom with your own. -- Add your desired beacon adapter to the pom.xml in the commented out section -- Deploy The beacon -- Run the test-managed profile to ensure the beacon works and complies with the beacon spec - -The API takes care of the rest and provides the following endpoints upon deployment of your beacon: +The Rest API provides the following endpoints upon deployment of your beacon: http://localhost:8080/beacon-java - information about your beacon http://localhost:8080/beacon-java/query - access to query service ##Technologies -Java EE. CDI, JAX-RS, JAXB. Tested with Arquillian/ShrinkWrap. +Java EE. CDI, JAX-RS, JAXB. Tested with Arquillian/ShrinkWrap. \ No newline at end of file diff --git a/beacon-java-rest/pom.xml b/beacon-java-rest/pom.xml index 8bf44eb..fb38dce 100644 --- a/beacon-java-rest/pom.xml +++ b/beacon-java-rest/pom.xml @@ -109,17 +109,15 @@ org.keycloak keycloak-servlet-filter-adapter - 2.0.0.Final org.keycloak keycloak-authz-client - 2.0.0.Final + org.apache.httpcomponents httpclient - 4.5.2 diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/BeaconApplication.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/BeaconApplication.java index a11c139..0829cef 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/BeaconApplication.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/BeaconApplication.java @@ -25,8 +25,6 @@ import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; -import java.util.HashSet; -import java.util.Set; /** * REST beacon application. diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconQuery.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconQuery.java index de7b7d3..986edfd 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconQuery.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconQuery.java @@ -23,7 +23,6 @@ */ package com.dnastack.beacon.rest.endpoints; -import com.dnastack.beacon.rest.exceptions.BeaconException; import com.dnastack.beacon.rest.exceptions.InvalidAlleleRequestException; import org.ga4gh.beacon.BeaconAlleleRequest; import org.ga4gh.beacon.BeaconAlleleResponse; @@ -35,7 +34,7 @@ import java.util.List; /** - * Beacon rest resource for querying alle information from a beacon + * Beacon rest resource for querying allele information from a beacon. * * @author Miroslav Cupak (mirocupak@gmail.com) * @author Patrick Magee (patrickmageee@gmail.com) @@ -47,18 +46,19 @@ public interface BeaconQuery { /** * Query a beacon resource for information on whether an allele exists or not. Optionally includes the datasets. - * Returns the completed BeaconAlleleResponse, Or a BeaconAlleleResponse with a BeaconError object if an error + * Returns the completed BeaconAlleleResponse or a BeaconAlleleResponse with a BeaconError object if an error * was encountered. * - * @param referenceName Name of the chromosome or contig + * @param referenceName reference name (chromosome). Accepted values: 1-22, X, Y * @param start 0-base start position - * @param referenceBases String of reference bases - * @param alternateBases String of alternate bases - * @param assemblyId String of assembly build version - * @param datasetIds List of dataset Ids - * @param includeDatasetResponses Boolean value to include Dataset responses - * @return Completed Beacon response object - * @throws BeaconException + * @param referenceBases reference bases for this variant (starting from `start`). Accepted values: see the + * REF field in VCF 4.2 specification (https://samtools.github.io/hts-specs/VCFv4.2.pdf) + * @param alternateBases the bases that appear instead of the reference bases. Accepted values: see the ALT + * field in VCF 4.2 specification (https://samtools.github.io/hts-specs/VCFv4.2.pdf) + * @param assemblyId assembly identifier (GRC notation, e.g. `GRCh37`) + * @param datasetIds identifiers of datasets. If this field is null, all datasets will be queried + * @param includeDatasetResponses indicator of whether responses for individual datasets should be included (not null) + * in the response. If null, the default value of false is assumed */ @GET @Produces({MediaType.APPLICATION_JSON}) @@ -75,12 +75,10 @@ BeaconAlleleResponse query(@QueryParam("referenceName") String referenceName, * Query a beacon resource for information on whether an allele exists or not. Optionally includes the datasets. * Returns the completed BeaconAlleleResponse, Or a BeaconAlleleResponse with a BeaconError object if an error * was encountered. - * - * @param request Completed Beacon response object */ @POST @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) - BeaconAlleleResponse query(BeaconAlleleRequest request) throws InvalidAlleleRequestException; + BeaconAlleleResponse query(BeaconAlleleRequest request, @Context HttpServletRequest servletRequest) throws InvalidAlleleRequestException; } diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconInfoImpl.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconInfoImpl.java index b9867cd..e5204d9 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconInfoImpl.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconInfoImpl.java @@ -27,8 +27,6 @@ import com.dnastack.beacon.rest.endpoints.BeaconInfo; import com.dnastack.beacon.rest.exceptions.BeaconException; import org.ga4gh.beacon.Beacon; -import org.keycloak.AuthorizationContext; -import org.keycloak.KeycloakSecurityContext; import javax.inject.Inject; import javax.ws.rs.GET; diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconQueryImpl.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconQueryImpl.java index e7324ad..d81578c 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconQueryImpl.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconQueryImpl.java @@ -35,6 +35,7 @@ import javax.inject.Inject; import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.BadRequestException; import javax.ws.rs.Path; import javax.ws.rs.core.Context; import javax.ws.rs.core.Request; @@ -54,10 +55,6 @@ public class BeaconQueryImpl implements BeaconQuery { public BeaconAlleleResponse query(String referenceName, Long start, String referenceBases, String alternateBases, String assemblyId, List datasetIds, Boolean includeDatasetResponses, @Context HttpServletRequest servletRequest) throws InvalidAlleleRequestException { - - KeycloakSecurityContext keycloakSecurityContext = (KeycloakSecurityContext) servletRequest.getAttribute(KeycloakSecurityContext.class.getName()); - AuthorizationContext authzContext = keycloakSecurityContext.getAuthorizationContext(); - validateRequest(referenceName, start, referenceBases, alternateBases, assemblyId); BeaconAlleleRequest request = BeaconAlleleRequest.newBuilder() .setReferenceName(referenceName) @@ -73,7 +70,7 @@ public BeaconAlleleResponse query(String referenceName, Long start, String refer } @Override - public BeaconAlleleResponse query(BeaconAlleleRequest request) throws InvalidAlleleRequestException { + public BeaconAlleleResponse query(BeaconAlleleRequest request, @Context HttpServletRequest servletRequest) throws InvalidAlleleRequestException { validateRequest(request); return service.getBeaconAlleleResponse(request); } @@ -89,7 +86,7 @@ private void validateRequest(BeaconAlleleRequest request) throws InvalidAlleleRe } /** - * Validate the beacon fields according to the 0.3.0 beacon specifications. + * Validates the request parameters according to the 0.3.0 beacon specifications. */ private void validateRequest(String referenceName, Long start, String referenceBases, String alternateBases, String assemblyId) throws InvalidAlleleRequestException { boolean isValidReferenceName = StringUtils.isNotBlank(referenceName); diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/secured/SecuredBeaconQueryImpl.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/secured/SecuredBeaconQueryImpl.java new file mode 100644 index 0000000..080833d --- /dev/null +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/secured/SecuredBeaconQueryImpl.java @@ -0,0 +1,105 @@ +package com.dnastack.beacon.rest.endpoints.impl.secured; + +import com.dnastack.beacon.rest.endpoints.BeaconQuery; +import com.dnastack.beacon.rest.endpoints.impl.BeaconQueryImpl; +import com.dnastack.beacon.rest.exceptions.InvalidAlleleRequestException; +import com.dnastack.beacon.rest.sys.security.SecurityContext; +import org.apache.commons.collections.CollectionUtils; +import org.ga4gh.beacon.BeaconAlleleRequest; +import org.ga4gh.beacon.BeaconAlleleResponse; +import org.ga4gh.beacon.BeaconDatasetAlleleResponse; +import org.keycloak.AuthorizationContext; +import org.keycloak.KeycloakSecurityContext; +import org.keycloak.representations.authorization.Permission; + +import javax.decorator.Decorator; +import javax.decorator.Delegate; +import javax.enterprise.inject.Any; +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.core.Context; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Decorates the original {@link BeaconQueryImpl} to enforce security constraints. + * Role-based access is automatically checked by the Keycloak filter, this class handles more detailed security constraints. + * + * @author Artem (tema.voskoboynick@gmail.com) + * @version 1.0 + */ +@Decorator +public class SecuredBeaconQueryImpl implements BeaconQuery { + + /** + * Public role is like an admin role - can view anything. + */ + private static final String PUBLIC_ROLE = "public"; + + /** + * Users with Registered role are allowed to view only answers yes/no. + * But individual users are allowed to view individual dataset responses. + */ + private static final String REGISTERED_ROLE = "registered"; + + /** + * In Keycloak, a dataset resource name is in the "Dataset:[dataset_id]" format. + * Allowed dataset IDs are retrieved by removing the "Dataset:" prefix. + */ + private static final String DATASET_RESOURCES_PREFIX = "Dataset:"; + + @Delegate + @Any + @Inject + private BeaconQuery delegate; + + @Inject + private SecurityContext securityContext; + + @Override + public BeaconAlleleResponse query(String referenceName, Long start, String referenceBases, String alternateBases, String assemblyId, List datasetIds, Boolean includeDatasetResponses, @Context HttpServletRequest servletRequest) throws InvalidAlleleRequestException { + BeaconAlleleResponse response = delegate.query(referenceName, start, referenceBases, alternateBases, assemblyId, datasetIds, includeDatasetResponses, servletRequest); + ensureSecurityConstraints(servletRequest, response); + return response; + } + + @Override + public BeaconAlleleResponse query(BeaconAlleleRequest request, @Context HttpServletRequest servletRequest) throws InvalidAlleleRequestException { + BeaconAlleleResponse response = delegate.query(request, servletRequest); + ensureSecurityConstraints(servletRequest, response); + return response; + } + + private void ensureSecurityConstraints(HttpServletRequest servletRequest, BeaconAlleleResponse response) { + if (!securityContext.isSecurityEnabled()) { + return; + } + + if (servletRequest.isUserInRole(PUBLIC_ROLE)) { + return; + } + + if (servletRequest.isUserInRole(REGISTERED_ROLE)) { + excludeUnauthorizedDatasets(servletRequest, response.getDatasetAlleleResponses()); + } + } + + private void excludeUnauthorizedDatasets(HttpServletRequest servletRequest, List datasetResponses) { + if (CollectionUtils.isNotEmpty(datasetResponses)) { + Set permittedDatasetIds = getPermittedDatasetIds(servletRequest); + datasetResponses.removeIf(datasetResponse -> !permittedDatasetIds.contains(datasetResponse.getDatasetId())); + } + } + + private Set getPermittedDatasetIds(HttpServletRequest servletRequest) { + KeycloakSecurityContext keycloakSecurityContext = (KeycloakSecurityContext) servletRequest.getAttribute(KeycloakSecurityContext.class.getName()); + AuthorizationContext authzContext = keycloakSecurityContext.getAuthorizationContext(); + + List permissions = authzContext.getPermissions(); + return permissions.stream() + .filter(permission -> permission.getResourceSetName().startsWith(DATASET_RESOURCES_PREFIX)) + .map(permission -> permission.getResourceSetName().substring(DATASET_RESOURCES_PREFIX.length())) + .collect(Collectors.toSet()); + } +} diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/exceptions/BeaconException.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/exceptions/BeaconException.java index f9424dc..19b657a 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/exceptions/BeaconException.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/exceptions/BeaconException.java @@ -1,6 +1,8 @@ package com.dnastack.beacon.rest.exceptions; /** + * Base class for all checked Beacon exceptions. + * * @author Artem (tema.voskoboynick@gmail.com) * @version 1.0 */ diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/BeaconExceptionHandler.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/BeaconExceptionHandler.java index b829359..54de50a 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/BeaconExceptionHandler.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/BeaconExceptionHandler.java @@ -13,6 +13,8 @@ import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; /** + * Captures all Beacon exceptions and creates corresponding responses. + * * @author patmagee * @author Artem (tema.voskoboynick@gmail.com) * @version 1.0 @@ -20,12 +22,6 @@ @Provider public class BeaconExceptionHandler implements ExceptionMapper { - /** - * Default error handler to capture all errors and send the user a JSON response - * with the status code, reason, message and stacktrace of the error - * - * @return response with the status and error entity - */ @Override public Response toResponse(BeaconException exception) { if (exception instanceof InvalidAlleleRequestException) { @@ -35,6 +31,10 @@ public Response toResponse(BeaconException exception) { } } + /** + * Due to backward compatibility issues, the response on Beacon Query request should always be of the {@link BeaconAlleleResponse} type, + * and any errors, if any, are stored inside it. + */ private Response handleInvalidAlleleRequestException(InvalidAlleleRequestException exception) { BeaconAlleleResponse response = new BeaconAlleleResponse(); response.setAlleleRequest(exception.getRequest()); diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/DefaultExceptionHandler.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/DefaultExceptionHandler.java index 944343c..6915686 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/DefaultExceptionHandler.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/DefaultExceptionHandler.java @@ -25,7 +25,6 @@ import org.ga4gh.beacon.BeaconError; -import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; @@ -34,7 +33,7 @@ import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; /** - * Default Exception handler to catch all Non Beacon exceptions thrown by the rest resources. + * Catches all non Beacon exceptions thrown by the rest resources. * * @author patmagee * @author Artem (tema.voskoboynick@gmail.com) @@ -42,12 +41,6 @@ @Provider public class DefaultExceptionHandler implements ExceptionMapper { - /** - * Default error handler to capture all errors and send the user a JSON response - * with the status code, reason, message and stacktrace of the error - * - * @return response with the status and error entity - */ @Override public Response toResponse(Throwable exception) { BeaconError response = BeaconError.newBuilder() diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/security/ConfigurableKeycloakOIDCFilter.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/security/ConfigurableKeycloakOIDCFilter.java new file mode 100644 index 0000000..586d409 --- /dev/null +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/security/ConfigurableKeycloakOIDCFilter.java @@ -0,0 +1,35 @@ +package com.dnastack.beacon.rest.sys.security; + +import org.keycloak.adapters.servlet.KeycloakOIDCFilter; + +import javax.inject.Inject; +import javax.servlet.*; +import java.io.IOException; + +/** + * Extends Keycloak security filter to allow enabling/disabling it depending on a context parameter. + * + * @author Artem (tema.voskoboynick@gmail.com) + * @version 1.0 + */ +public class ConfigurableKeycloakOIDCFilter extends KeycloakOIDCFilter { + + @Inject + private SecurityContext securityContext; + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + if (securityContext.isSecurityEnabled()) { + super.init(filterConfig); + } + } + + @Override + public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { + if (securityContext.isSecurityEnabled()) { + super.doFilter(req, res, chain); + } else { + chain.doFilter(req, res); + } + } +} diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/security/SecurityContext.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/security/SecurityContext.java new file mode 100644 index 0000000..f66c186 --- /dev/null +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/security/SecurityContext.java @@ -0,0 +1,19 @@ +package com.dnastack.beacon.rest.sys.security; + +import javax.enterprise.context.Dependent; +import javax.inject.Inject; +import javax.servlet.ServletContext; + +/** + * @author Artem (tema.voskoboynick@gmail.com) + * @version 1.0 + */ +@Dependent +public class SecurityContext { + @Inject + private ServletContext servletContext; + + public boolean isSecurityEnabled() { + return Boolean.parseBoolean(servletContext.getInitParameter("keycloak.security.enabled")); + } +} diff --git a/beacon-java-rest/src/main/webapp/META-INF/beans.xml b/beacon-java-rest/src/main/webapp/META-INF/beans.xml deleted file mode 100644 index f806c1b..0000000 --- a/beacon-java-rest/src/main/webapp/META-INF/beans.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - com.dnastack.beacon.core.service.test.MyInterrfaceSecondImpl - - \ No newline at end of file diff --git a/beacon-java-rest/src/main/webapp/WEB-INF/beans.xml b/beacon-java-rest/src/main/webapp/WEB-INF/beans.xml index 9517ba1..5416028 100644 --- a/beacon-java-rest/src/main/webapp/WEB-INF/beans.xml +++ b/beacon-java-rest/src/main/webapp/WEB-INF/beans.xml @@ -1,9 +1,8 @@ + bean-discovery-mode="all" version="1.2"> - com.dnastack.beacon.core.service.test.MyInterrfaceSecondImpl + com.dnastack.beacon.rest.endpoints.impl.secured.SecuredBeaconQueryImpl \ No newline at end of file diff --git a/beacon-java-rest/src/main/webapp/WEB-INF/web.xml b/beacon-java-rest/src/main/webapp/WEB-INF/web.xml index 5fa8380..696d190 100644 --- a/beacon-java-rest/src/main/webapp/WEB-INF/web.xml +++ b/beacon-java-rest/src/main/webapp/WEB-INF/web.xml @@ -17,14 +17,21 @@ + + + Keycloak Filter - org.keycloak.adapters.servlet.KeycloakOIDCFilter + com.dnastack.beacon.rest.sys.security.ConfigurableKeycloakOIDCFilter Keycloak Filter /keycloak/* - /protected/* /query/* diff --git a/pom.xml b/pom.xml index 819a310..5b78610 100644 --- a/pom.xml +++ b/pom.xml @@ -65,6 +65,8 @@ 3.4.1 1.0-SNAPSHOT 8.2.1.Final + 2.0.0.Final + 4.5.2 @@ -145,6 +147,21 @@ ${version.org.wildfly} test + + org.keycloak + keycloak-servlet-filter-adapter + ${version.keycloak} + + + org.keycloak + keycloak-authz-client + ${version.keycloak} + + + org.apache.httpcomponents + httpclient + ${version.httpcomponents} + diff --git a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/BeaconService.java b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/BeaconService.java index 3c56f89..ea4ba50 100644 --- a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/BeaconService.java +++ b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/BeaconService.java @@ -5,6 +5,8 @@ import org.ga4gh.beacon.BeaconAlleleResponse; /** + * Implement this service accordingly to your Beacon. + * * @author Artem (tema.voskoboynick@gmail.com) * @version 1.0 */ diff --git a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleBeaconServiceImpl.java b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleBeaconServiceImpl.java index b2fbb94..486399d 100644 --- a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleBeaconServiceImpl.java +++ b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleBeaconServiceImpl.java @@ -24,13 +24,11 @@ package com.dnastack.beacon.core.service.impl; import com.dnastack.beacon.core.service.BeaconService; -import com.dnastack.beacon.core.service.test.MyInterface; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.BooleanUtils; import org.ga4gh.beacon.*; import javax.enterprise.context.Dependent; -import javax.inject.Inject; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -45,12 +43,8 @@ @Dependent public class SampleBeaconServiceImpl implements BeaconService { - @Inject - private MyInterface myInterface; - @Override public Beacon getBeacon() { - myInterface.hello(); return SampleData.BEACON; } diff --git a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleData.java b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleData.java index cab54e5..e6d9fc5 100644 --- a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleData.java +++ b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleData.java @@ -27,13 +27,10 @@ import avro.shaded.com.google.common.collect.ImmutableMap; import org.ga4gh.beacon.*; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; +import java.util.*; /** - * This class simply is acting as a datastorage for the BeaconAdapter to perform lookups on + * Sample data holder. * * @author patmagee * @author Artem (tema.voskoboynick@gmail.com) @@ -58,6 +55,12 @@ public class SampleData { .setInfo(ImmutableMap.of("note", "This is a Sample Dataset")) .build(); + BeaconDataset dataset2 = BeaconDataset.newBuilder(dataset) + .setId("sample_dataset_id_2") + .setName("Second Sample Dataset") + .build(); + + BASE_DATASET_RESPONSE = BeaconDatasetAlleleResponse.newBuilder() .setCallCount(1L) .setFrequency(0.221) @@ -69,8 +72,8 @@ public class SampleData { .setExists(null) // Setting nulls explicitly required by avro. .build(); - BeaconAlleleRequest request = BeaconAlleleRequest.newBuilder() - .setDatasetIds(Collections.singletonList(dataset.getId())) + BeaconAlleleRequest sampleRequest = BeaconAlleleRequest.newBuilder() + .setDatasetIds(Arrays.asList(dataset.getId(), dataset2.getId())) .setReferenceName("1") .setAssemblyId("GRCh37") .setIncludeDatasetResponses(true) @@ -82,14 +85,15 @@ public class SampleData { DATASETS = new HashMap() { { Map bases = ImmutableMap.of( - "referenceBases", request.getReferenceBases(), - "alternateBases", request.getAlternateBases() + "referenceBases", sampleRequest.getReferenceBases(), + "alternateBases", sampleRequest.getAlternateBases() ); - Map positions = ImmutableMap.of(request.getStart(), bases); - Map references = ImmutableMap.of(request.getReferenceName(), positions); - Map assemblies = ImmutableMap.of(request.getAssemblyId(), references); + Map positions = ImmutableMap.of(sampleRequest.getStart(), bases); + Map references = ImmutableMap.of(sampleRequest.getReferenceName(), positions); + Map assemblies = ImmutableMap.of(sampleRequest.getAssemblyId(), references); put(dataset.getId(), assemblies); + put(dataset2.getId(), assemblies); } }; @@ -114,7 +118,7 @@ public class SampleData { .setDatasets(Collections.singletonList(dataset)) .setCreateDateTime(new Date().toString()) .setUpdateDateTime(new Date().toString()) - .setSampleAlleleRequests(Collections.singletonList(request)) + .setSampleAlleleRequests(Collections.singletonList(sampleRequest)) .setOrganization(organization) .setId("sample_beacon_id") .setInfo(ImmutableMap.of("note", "This is a sample Beacon")) diff --git a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterface.java b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterface.java deleted file mode 100644 index fe2bd5b..0000000 --- a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterface.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.dnastack.beacon.core.service.test; - -/** - * @author Artem (tema.voskoboynick@gmail.com) - * @version 1.0 - */ -public interface MyInterface { - void hello(); -} diff --git a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterfaceImpl.java b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterfaceImpl.java deleted file mode 100644 index 4994a22..0000000 --- a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterfaceImpl.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.dnastack.beacon.core.service.test; - -import javax.enterprise.context.Dependent; - -/** - * @author Artem (tema.voskoboynick@gmail.com) - * @version 1.0 - */ -@Dependent -public class MyInterfaceImpl implements MyInterface { - @Override - public void hello() { - System.out.println("hello"); - } -} diff --git a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterrfaceSecondImpl.java b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterrfaceSecondImpl.java deleted file mode 100644 index b368b6b..0000000 --- a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/test/MyInterrfaceSecondImpl.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.dnastack.beacon.core.service.test; - -import com.dnastack.beacon.core.service.BeaconService; - -import javax.decorator.Decorator; -import javax.decorator.Delegate; -import javax.enterprise.inject.Any; -import javax.inject.Inject; - -/** - * @author Artem (tema.voskoboynick@gmail.com) - * @version 1.0 - */ -@Decorator -public class MyInterrfaceSecondImpl implements MyInterface { - - @Inject - @Delegate - @Any - private MyInterface MyInterface; - - @Override - public void hello() { - System.out.println("hello EXTENDED"); - } -} From fed5a55894c6766edf5f5ca98a8fed69249a3dca Mon Sep 17 00:00:00 2001 From: artemik Date: Mon, 15 Aug 2016 21:10:59 +0400 Subject: [PATCH 5/5] put in use Beacon Adapter API, made according changes --- README.md | 65 +++++++------------ beacon-java-rest/pom.xml | 12 ++-- .../beacon/rest/endpoints/BeaconInfo.java | 2 +- .../beacon/rest/endpoints/BeaconQuery.java | 6 +- .../rest/endpoints/impl/BeaconInfoImpl.java | 8 +-- .../rest/endpoints/impl/BeaconQueryImpl.java | 34 +++++----- .../impl/secured/SecuredBeaconQueryImpl.java | 6 +- .../rest/exceptions/BeaconException.java | 18 ----- .../InvalidAlleleRequestException.java | 29 --------- .../rest/sys/BeaconExceptionHandler.java | 10 +-- .../src/main/webapp/WEB-INF/web.xml | 7 +- pom.xml | 7 +- .../pom.xml | 8 ++- .../adapter/sample/SampleBeaconAdapter.java | 30 ++++++++- .../beacon/adapter/sample}/SampleData.java | 2 +- .../beacon/core/service/BeaconService.java | 17 ----- 16 files changed, 107 insertions(+), 154 deletions(-) delete mode 100644 beacon-java-rest/src/main/java/com/dnastack/beacon/rest/exceptions/BeaconException.java delete mode 100644 beacon-java-rest/src/main/java/com/dnastack/beacon/rest/exceptions/InvalidAlleleRequestException.java rename {sample-beacon-service => sample-beacon-adapter}/pom.xml (92%) rename sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleBeaconServiceImpl.java => sample-beacon-adapter/src/main/java/com/dnastack/beacon/adapter/sample/SampleBeaconAdapter.java (82%) rename {sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl => sample-beacon-adapter/src/main/java/com/dnastack/beacon/adapter/sample}/SampleData.java (99%) delete mode 100644 sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/BeaconService.java diff --git a/README.md b/README.md index 6aa63ee..c74a838 100644 --- a/README.md +++ b/README.md @@ -9,40 +9,23 @@ * [How it works](#how-it-works) * [Technologies](#technologies) -##What it is -This project contains the BDK (beacon development kit) for Java (EE) developers. The BDK provides all of the tools required to create a basic rest implementation for a beacon almost straight out of the box with only minimal set up required. -Users can extend the BDK to make it fit within their own project, or use it as is defining their own service to retrieve data from their preferred data source. - -##System requirements -All you need to build this project is Java 8.0 (Java SDK 1.8) or later, Maven 3.0 or later. Since the project is Java EE based, an application server with support for Java EE 7 is needed to deploy the application (e.g. JBoss EAP or WildFly). - -##Modules -1. [beacon-java-core](/beacon-java-core) - Contains core classes and functions shared across modules in the BJDK. -2. [beacon-java-rest](/beacon-java-rest) - Rest implementation of a beacon, configured to run on a JBOSS server. -3. [sample-beacon-adapter](/sample-beacon-adapter) - Sample beacon adapter implementation - -## Beacon Specification -The BDK implements the beacon specification and relies on the data models generated by the beacon schema. At the moment the dependency is not currently listed on maven central but can be retrived from the [beacon teams git hub repository](https://github.com/ga4gh/beacon-team). - -To retrieve the dependency: - -``` -git clone https://github.com/ga4gh/beacon-team -cd beacon-team -mvn clean install -``` - -## How it Works -The project provides the following: - -- Rest API -- sample beacon service implementation -- sample test suite - -##How to run it +## What it is +This project contains the BDK (beacon development kit) for Java EE developers. The BDK provides all of the tools required +to create a basic rest implementation for a beacon almost straight out of the box with only minimal set up required. +Extend the BDK to make it fit within their own project, or use it as is defining your own adapter to retrieve data from +your preferred data source. + +## System Requirements +- Java 8 or later; +- Maven 3.0 or later; +- [Beacon Schemas (v.0.3.0)](https://github.com/ga4gh/beacon-team): BDK relies on the generated Java classes; +- an application server with support for Java EE 7 (e.g. JBoss EAP or WildFly). + +## Modules +- [beacon-java-rest](/beacon-java-rest): rest implementation of a beacon, configured to run on a JBoss server; +- [sample-beacon-adapter](/sample-beacon-adapter): sample beacon adapter implementation. + +## How to run it Build the project: mvn clean install @@ -61,12 +44,14 @@ In order to run the tests from beacon-java-rest in a managed (remote) container, mvn test -Ptest-managed -##Creating a beacon -Beacon REST API uses Beacon Service to retrieve the beacon data. The BDK ships with a sample Beacon Service that uses sample data. -The sample Beacon Service is intended to be a placeholder to allow the tests to be run, and to give the user an idea of how to implement a beacon. +## Creating a Beacon +Beacon REST API uses Beacon Adapter to retrieve the beacon data. The BDK ships with a sample Beacon Adapter that uses +sample data. The sample Beacon Adapter is intended to be a placeholder to allow the tests to be run, and to give the user +an idea of how to implement a beacon. -Once you are ready, implement your own [beacon-service](https://github.com/mcupak/beacon-service) project to use query own data. -To switch to your own Beacon Service, simply replace the service dependency in the beacon-java-rest's pom with your own. +Once you are ready, implement your own [beacon-adapter](https://github.com/mcupak/beacon-service) project to query your +own data. To switch to your own Beacon Adapter, simply replace the adapter dependency in the beacon-java-rest's pom with +your own. The Rest API provides the following endpoints upon deployment of your beacon: @@ -74,5 +59,5 @@ The Rest API provides the following endpoints upon deployment of your beacon: http://localhost:8080/beacon-java/query - access to query service -##Technologies +## Technologies Java EE. CDI, JAX-RS, JAXB. Tested with Arquillian/ShrinkWrap. \ No newline at end of file diff --git a/beacon-java-rest/pom.xml b/beacon-java-rest/pom.xml index fb38dce..cf99540 100644 --- a/beacon-java-rest/pom.xml +++ b/beacon-java-rest/pom.xml @@ -119,15 +119,17 @@ org.apache.httpcomponents httpclient - - com.dnastack - sample-beacon-service + beacon-adapter-api + ${version.beacon.adapter.api} + + + + com.dnastack + sample-beacon-adapter ${project.version} - - diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconInfo.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconInfo.java index b2b457b..2de6587 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconInfo.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconInfo.java @@ -23,7 +23,7 @@ */ package com.dnastack.beacon.rest.endpoints; -import com.dnastack.beacon.rest.exceptions.BeaconException; +import com.dnastack.beacon.exceptions.BeaconException; import org.ga4gh.beacon.Beacon; import javax.ws.rs.GET; diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconQuery.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconQuery.java index 986edfd..ebfacae 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconQuery.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/BeaconQuery.java @@ -23,7 +23,7 @@ */ package com.dnastack.beacon.rest.endpoints; -import com.dnastack.beacon.rest.exceptions.InvalidAlleleRequestException; +import com.dnastack.beacon.exceptions.BeaconException; import org.ga4gh.beacon.BeaconAlleleRequest; import org.ga4gh.beacon.BeaconAlleleResponse; @@ -69,7 +69,7 @@ BeaconAlleleResponse query(@QueryParam("referenceName") String referenceName, @QueryParam("assemblyId") String assemblyId, @QueryParam("datasetIds") List datasetIds, @QueryParam("includeDatasetResponses") Boolean includeDatasetResponses, - @Context HttpServletRequest servletRequest) throws InvalidAlleleRequestException; + @Context HttpServletRequest servletRequest) throws BeaconException; /** * Query a beacon resource for information on whether an allele exists or not. Optionally includes the datasets. @@ -79,6 +79,6 @@ BeaconAlleleResponse query(@QueryParam("referenceName") String referenceName, @POST @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) - BeaconAlleleResponse query(BeaconAlleleRequest request, @Context HttpServletRequest servletRequest) throws InvalidAlleleRequestException; + BeaconAlleleResponse query(BeaconAlleleRequest request, @Context HttpServletRequest servletRequest) throws BeaconException; } diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconInfoImpl.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconInfoImpl.java index e5204d9..fd97da5 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconInfoImpl.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconInfoImpl.java @@ -23,9 +23,9 @@ */ package com.dnastack.beacon.rest.endpoints.impl; -import com.dnastack.beacon.core.service.BeaconService; +import com.dnastack.beacon.adapter.api.BeaconAdapter; +import com.dnastack.beacon.exceptions.BeaconException; import com.dnastack.beacon.rest.endpoints.BeaconInfo; -import com.dnastack.beacon.rest.exceptions.BeaconException; import org.ga4gh.beacon.Beacon; import javax.inject.Inject; @@ -41,12 +41,12 @@ public class BeaconInfoImpl implements BeaconInfo { @Inject - private BeaconService service; + private BeaconAdapter adapter; @GET @Override @Produces({MediaType.APPLICATION_JSON}) public Beacon info() throws BeaconException { - return service.getBeacon(); + return adapter.getBeacon(); } } diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconQueryImpl.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconQueryImpl.java index d81578c..7b10820 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconQueryImpl.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/BeaconQueryImpl.java @@ -23,22 +23,20 @@ */ package com.dnastack.beacon.rest.endpoints.impl; -import com.dnastack.beacon.core.service.BeaconService; +import com.dnastack.beacon.adapter.api.BeaconAdapter; +import com.dnastack.beacon.exceptions.BeaconAlleleRequestException; +import com.dnastack.beacon.exceptions.BeaconException; import com.dnastack.beacon.rest.endpoints.BeaconQuery; -import com.dnastack.beacon.rest.exceptions.InvalidAlleleRequestException; +import com.dnastack.beacon.utils.Reason; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.ga4gh.beacon.BeaconAlleleRequest; import org.ga4gh.beacon.BeaconAlleleResponse; -import org.keycloak.AuthorizationContext; -import org.keycloak.KeycloakSecurityContext; import javax.inject.Inject; import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.BadRequestException; import javax.ws.rs.Path; import javax.ws.rs.core.Context; -import javax.ws.rs.core.Request; import java.util.List; /** @@ -49,12 +47,12 @@ public class BeaconQueryImpl implements BeaconQuery { @Inject - private BeaconService service; + private BeaconAdapter adapter; @Override public BeaconAlleleResponse query(String referenceName, Long start, String referenceBases, String alternateBases, String assemblyId, List datasetIds, Boolean includeDatasetResponses, @Context HttpServletRequest servletRequest) - throws InvalidAlleleRequestException { + throws BeaconException { validateRequest(referenceName, start, referenceBases, alternateBases, assemblyId); BeaconAlleleRequest request = BeaconAlleleRequest.newBuilder() .setReferenceName(referenceName) @@ -66,20 +64,20 @@ public BeaconAlleleResponse query(String referenceName, Long start, String refer .setIncludeDatasetResponses(BooleanUtils.isTrue(includeDatasetResponses)) .build(); - return service.getBeaconAlleleResponse(request); + return adapter.getBeaconAlleleResponse(request); } @Override - public BeaconAlleleResponse query(BeaconAlleleRequest request, @Context HttpServletRequest servletRequest) throws InvalidAlleleRequestException { + public BeaconAlleleResponse query(BeaconAlleleRequest request, @Context HttpServletRequest servletRequest) throws BeaconException { validateRequest(request); - return service.getBeaconAlleleResponse(request); + return adapter.getBeaconAlleleResponse(request); } - private void validateRequest(BeaconAlleleRequest request) throws InvalidAlleleRequestException { + private void validateRequest(BeaconAlleleRequest request) throws BeaconAlleleRequestException { throwIf(request == null, "Request can't be null", request); try { validateRequest(request.getReferenceName(), request.getStart(), request.getReferenceBases(), request.getAlternateBases(), request.getAssemblyId()); - } catch (InvalidAlleleRequestException e) { + } catch (BeaconAlleleRequestException e) { e.setRequest(request); throw e; } @@ -88,7 +86,7 @@ private void validateRequest(BeaconAlleleRequest request) throws InvalidAlleleRe /** * Validates the request parameters according to the 0.3.0 beacon specifications. */ - private void validateRequest(String referenceName, Long start, String referenceBases, String alternateBases, String assemblyId) throws InvalidAlleleRequestException { + private void validateRequest(String referenceName, Long start, String referenceBases, String alternateBases, String assemblyId) throws BeaconAlleleRequestException { boolean isValidReferenceName = StringUtils.isNotBlank(referenceName); boolean isValidStart = start != null && start >= 0; boolean isValidReferenceBases = StringUtils.isNotBlank(referenceBases); @@ -102,15 +100,15 @@ private void validateRequest(String referenceName, Long start, String referenceB throwIf(!isValidAssemblyId, "Assembly ID can't be null, should start with GRCh"); } - private static void throwIf(boolean expression, String message) throws InvalidAlleleRequestException { + private static void throwIf(boolean expression, String message) throws BeaconAlleleRequestException { if (expression) { - throw new InvalidAlleleRequestException(message); + throw new BeaconAlleleRequestException(Reason.INVALID_REQUEST, message); } } - private static void throwIf(boolean expression, String message, BeaconAlleleRequest request) throws InvalidAlleleRequestException { + private static void throwIf(boolean expression, String message, BeaconAlleleRequest request) throws BeaconAlleleRequestException { if (expression) { - throw new InvalidAlleleRequestException(request, message); + throw new BeaconAlleleRequestException(message, Reason.INVALID_REQUEST, request); } } } diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/secured/SecuredBeaconQueryImpl.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/secured/SecuredBeaconQueryImpl.java index 080833d..bb76dd4 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/secured/SecuredBeaconQueryImpl.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/endpoints/impl/secured/SecuredBeaconQueryImpl.java @@ -1,8 +1,8 @@ package com.dnastack.beacon.rest.endpoints.impl.secured; +import com.dnastack.beacon.exceptions.BeaconException; import com.dnastack.beacon.rest.endpoints.BeaconQuery; import com.dnastack.beacon.rest.endpoints.impl.BeaconQueryImpl; -import com.dnastack.beacon.rest.exceptions.InvalidAlleleRequestException; import com.dnastack.beacon.rest.sys.security.SecurityContext; import org.apache.commons.collections.CollectionUtils; import org.ga4gh.beacon.BeaconAlleleRequest; @@ -58,14 +58,14 @@ public class SecuredBeaconQueryImpl implements BeaconQuery { private SecurityContext securityContext; @Override - public BeaconAlleleResponse query(String referenceName, Long start, String referenceBases, String alternateBases, String assemblyId, List datasetIds, Boolean includeDatasetResponses, @Context HttpServletRequest servletRequest) throws InvalidAlleleRequestException { + public BeaconAlleleResponse query(String referenceName, Long start, String referenceBases, String alternateBases, String assemblyId, List datasetIds, Boolean includeDatasetResponses, @Context HttpServletRequest servletRequest) throws BeaconException { BeaconAlleleResponse response = delegate.query(referenceName, start, referenceBases, alternateBases, assemblyId, datasetIds, includeDatasetResponses, servletRequest); ensureSecurityConstraints(servletRequest, response); return response; } @Override - public BeaconAlleleResponse query(BeaconAlleleRequest request, @Context HttpServletRequest servletRequest) throws InvalidAlleleRequestException { + public BeaconAlleleResponse query(BeaconAlleleRequest request, @Context HttpServletRequest servletRequest) throws BeaconException { BeaconAlleleResponse response = delegate.query(request, servletRequest); ensureSecurityConstraints(servletRequest, response); return response; diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/exceptions/BeaconException.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/exceptions/BeaconException.java deleted file mode 100644 index 19b657a..0000000 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/exceptions/BeaconException.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dnastack.beacon.rest.exceptions; - -/** - * Base class for all checked Beacon exceptions. - * - * @author Artem (tema.voskoboynick@gmail.com) - * @version 1.0 - */ -public class BeaconException extends Exception { - - public BeaconException() { - super(); - } - - public BeaconException(String message) { - super(message); - } -} diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/exceptions/InvalidAlleleRequestException.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/exceptions/InvalidAlleleRequestException.java deleted file mode 100644 index 63405ad..0000000 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/exceptions/InvalidAlleleRequestException.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.dnastack.beacon.rest.exceptions; - -import org.ga4gh.beacon.BeaconAlleleRequest; - -/** - * @author Artem (tema.voskoboynick@gmail.com) - * @version 1.0 - */ -public class InvalidAlleleRequestException extends BeaconException { - - private BeaconAlleleRequest request; - - public InvalidAlleleRequestException(String message) { - super(message); - } - - public InvalidAlleleRequestException(BeaconAlleleRequest request, String message) { - super(message); - this.request = request; - } - - public void setRequest(BeaconAlleleRequest request) { - this.request = request; - } - - public BeaconAlleleRequest getRequest() { - return request; - } -} diff --git a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/BeaconExceptionHandler.java b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/BeaconExceptionHandler.java index 54de50a..aa56589 100644 --- a/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/BeaconExceptionHandler.java +++ b/beacon-java-rest/src/main/java/com/dnastack/beacon/rest/sys/BeaconExceptionHandler.java @@ -1,7 +1,7 @@ package com.dnastack.beacon.rest.sys; -import com.dnastack.beacon.rest.exceptions.BeaconException; -import com.dnastack.beacon.rest.exceptions.InvalidAlleleRequestException; +import com.dnastack.beacon.exceptions.BeaconAlleleRequestException; +import com.dnastack.beacon.exceptions.BeaconException; import org.ga4gh.beacon.BeaconAlleleResponse; import org.ga4gh.beacon.BeaconError; @@ -24,8 +24,8 @@ public class BeaconExceptionHandler implements ExceptionMapper @Override public Response toResponse(BeaconException exception) { - if (exception instanceof InvalidAlleleRequestException) { - return handleInvalidAlleleRequestException((InvalidAlleleRequestException) exception); + if (exception instanceof BeaconAlleleRequestException) { + return handleBeaconAlleleRequestException((BeaconAlleleRequestException) exception); } else { return handleDefaultBeaconException(exception); } @@ -35,7 +35,7 @@ public Response toResponse(BeaconException exception) { * Due to backward compatibility issues, the response on Beacon Query request should always be of the {@link BeaconAlleleResponse} type, * and any errors, if any, are stored inside it. */ - private Response handleInvalidAlleleRequestException(InvalidAlleleRequestException exception) { + private Response handleBeaconAlleleRequestException(BeaconAlleleRequestException exception) { BeaconAlleleResponse response = new BeaconAlleleResponse(); response.setAlleleRequest(exception.getRequest()); response.setExists(null); diff --git a/beacon-java-rest/src/main/webapp/WEB-INF/web.xml b/beacon-java-rest/src/main/webapp/WEB-INF/web.xml index 696d190..abe14a0 100644 --- a/beacon-java-rest/src/main/webapp/WEB-INF/web.xml +++ b/beacon-java-rest/src/main/webapp/WEB-INF/web.xml @@ -17,13 +17,12 @@ - - + keycloak.security.enabled - true + false - --> Keycloak Filter diff --git a/pom.xml b/pom.xml index 5b78610..183b621 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ beacon-java - sample-beacon-service + sample-beacon-adapter beacon-java-rest @@ -162,6 +162,11 @@ httpclient ${version.httpcomponents} + + com.dnastack + beacon-adapter-api + ${version.beacon.adapter.api} + diff --git a/sample-beacon-service/pom.xml b/sample-beacon-adapter/pom.xml similarity index 92% rename from sample-beacon-service/pom.xml rename to sample-beacon-adapter/pom.xml index c9fd09c..67ebff3 100644 --- a/sample-beacon-service/pom.xml +++ b/sample-beacon-adapter/pom.xml @@ -34,8 +34,8 @@ 1.0-SNAPSHOT - sample-beacon-service - Sample Beacon Service + sample-beacon-adapter + Sample Beacon Adapter @@ -58,6 +58,10 @@ beacon ${version.beacon.api} + + com.dnastack + beacon-adapter-api + diff --git a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleBeaconServiceImpl.java b/sample-beacon-adapter/src/main/java/com/dnastack/beacon/adapter/sample/SampleBeaconAdapter.java similarity index 82% rename from sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleBeaconServiceImpl.java rename to sample-beacon-adapter/src/main/java/com/dnastack/beacon/adapter/sample/SampleBeaconAdapter.java index 486399d..1f54780 100644 --- a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleBeaconServiceImpl.java +++ b/sample-beacon-adapter/src/main/java/com/dnastack/beacon/adapter/sample/SampleBeaconAdapter.java @@ -21,9 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.dnastack.beacon.core.service.impl; +package com.dnastack.beacon.adapter.sample; -import com.dnastack.beacon.core.service.BeaconService; +import com.dnastack.beacon.adapter.api.BeaconAdapter; +import com.dnastack.beacon.utils.AdapterConfig; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.BooleanUtils; import org.ga4gh.beacon.*; @@ -37,17 +38,23 @@ import static javax.ws.rs.core.Response.Status; /** + * Beacon adapter that returns sample data. + * * @author Artem (tema.voskoboynick@gmail.com) * @author Patrick Magee (patrickmageee@gmail.com) */ @Dependent -public class SampleBeaconServiceImpl implements BeaconService { +public class SampleBeaconAdapter implements BeaconAdapter { @Override public Beacon getBeacon() { return SampleData.BEACON; } + @Override + public void initAdapter(AdapterConfig adapterConfig) { + } + @Override public BeaconAlleleResponse getBeaconAlleleResponse(BeaconAlleleRequest request) { BeaconAlleleResponse response = new BeaconAlleleResponse(); @@ -64,6 +71,23 @@ public BeaconAlleleResponse getBeaconAlleleResponse(BeaconAlleleRequest request) return response; } + @Override + public BeaconAlleleResponse getBeaconAlleleResponse(String referenceName, Long start, String referenceBases, String alternateBases, String assemblyId, List datasetIds, Boolean includeDatasetResponses) { + BeaconAlleleRequest request = createRequest(referenceName, start, referenceBases, alternateBases, assemblyId, datasetIds, includeDatasetResponses); + return getBeaconAlleleResponse(request); + } + + private BeaconAlleleRequest createRequest(String referenceName, Long start, String referenceBases, String alternateBases, String assemblyId, List datasetIds, Boolean includeDatasetResponses) { + return BeaconAlleleRequest.newBuilder() + .setReferenceName(referenceName) + .setStart(start) + .setReferenceBases(referenceBases) + .setAlternateBases(alternateBases) + .setAssemblyId(assemblyId) + .setDatasetIds(datasetIds) + .setIncludeDatasetResponses(includeDatasetResponses) + .build(); + } private DatasetsQueryResult queryDatasets(List datasetIds, String assemblyId, String referenceName, Long start, String referenceBases, String alternateBases) { diff --git a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleData.java b/sample-beacon-adapter/src/main/java/com/dnastack/beacon/adapter/sample/SampleData.java similarity index 99% rename from sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleData.java rename to sample-beacon-adapter/src/main/java/com/dnastack/beacon/adapter/sample/SampleData.java index e6d9fc5..a9de51b 100644 --- a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/impl/SampleData.java +++ b/sample-beacon-adapter/src/main/java/com/dnastack/beacon/adapter/sample/SampleData.java @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -package com.dnastack.beacon.core.service.impl; +package com.dnastack.beacon.adapter.sample; import avro.shaded.com.google.common.collect.ImmutableMap; import org.ga4gh.beacon.*; diff --git a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/BeaconService.java b/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/BeaconService.java deleted file mode 100644 index ea4ba50..0000000 --- a/sample-beacon-service/src/main/java/com/dnastack/beacon/core/service/BeaconService.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.dnastack.beacon.core.service; - -import org.ga4gh.beacon.Beacon; -import org.ga4gh.beacon.BeaconAlleleRequest; -import org.ga4gh.beacon.BeaconAlleleResponse; - -/** - * Implement this service accordingly to your Beacon. - * - * @author Artem (tema.voskoboynick@gmail.com) - * @version 1.0 - */ -public interface BeaconService { - BeaconAlleleResponse getBeaconAlleleResponse(BeaconAlleleRequest request); - - Beacon getBeacon(); -}