diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..ba866c4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +target/** +.kube diff --git a/Dockerfile b/Dockerfile new file mode 100755 index 0000000..4d0825c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,4 @@ +FROM websphere-liberty:microProfile +RUN installUtility install --acceptLicense logstashCollector-1.0 +COPY server.xml /config/server.xml +COPY target/microservice-schedule-1.0.0-SNAPSHOT.war /config/apps/schedule.war diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100755 index 0000000..c474909 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,21 @@ +#!groovy + +node('master') { + + // A collection of build utils. + def utils = load "/scripts/buildUtils.groovy" + + stage ('Extract') { + checkout scm + } + + stage ('Build') { + utils.mavenBuild ('clean', 'package') + utils.dockerBuild ('microservice-schedule') + } + + stage ('Deploy') { + utils.deploy () + } + +} diff --git a/README.md b/README.md index 8763bd0..21fb52e 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ -# sample.microservicebuilder.schedule \ No newline at end of file +# Microservice Builder Sample - Schedule microservice + +See the [sample documentation](/wasdev/sample.microservicebuilder.docs) for more information. diff --git a/manifests-secure/deploy-schedule.yaml b/manifests-secure/deploy-schedule.yaml new file mode 100755 index 0000000..26688aa --- /dev/null +++ b/manifests-secure/deploy-schedule.yaml @@ -0,0 +1,71 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: microservice-schedule-sample +spec: + replicas: 1 + template: + metadata: + labels: + name: schedule-deployment + spec: + containers: + - name: microservice-schedule + image: microservice-schedule:latest + env: + - name: EXTERNAL_IP_ADDR + valueFrom: + configMapKeyRef: + name: ipaddr-config + key: EXTERNAL_IP_ADDR + ports: + - containerPort: 9080 + imagePullPolicy: Never + volumeMounts: + - name: keystore + mountPath: /etc/wlp/config/keystore + - name: truststore + mountPath: /etc/wlp/config/truststore + - name: liberty-config + mountPath: /config/configDropins + imagePullPolicy: Never + volumes: + - name: keystore + secret: + secretName: wlp-keystore + - name: truststore + secret: + secretName: wlp-truststore + - name: liberty-config + configMap: + name: liberty-config + items: + - key: keystore.xml + path: defaults/keystore.xml + - key: logging.xml + path: defaults/logging.xml +--- +apiVersion: v1 +kind: Service +metadata: + name: schedule-service + namespace: default +spec: + ports: + - port: 9080 + selector: + name: schedule-deployment +--- +apiVersion: v1 +kind: Service +metadata: + name: schedule-service-nodeport + namespace: default +spec: + type: NodePort + ports: + - port: 9443 + nodePort: 31015 + + selector: + name: schedule-deployment diff --git a/manifests-secure/schedule-ingress.yaml b/manifests-secure/schedule-ingress.yaml new file mode 100755 index 0000000..5012fdc --- /dev/null +++ b/manifests-secure/schedule-ingress.yaml @@ -0,0 +1,15 @@ +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + annotations: + ingress.kubernetes.io/rewrite-target: /schedule + name: schedule-ingress +spec: + rules: + - host: + http: + paths: + - path: /schedule + backend: + serviceName: schedule-service + servicePort: 9080 \ No newline at end of file diff --git a/manifests/deploy-schedule.yaml b/manifests/deploy-schedule.yaml new file mode 100755 index 0000000..c42374f --- /dev/null +++ b/manifests/deploy-schedule.yaml @@ -0,0 +1,61 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: microservice-schedule-sample +spec: + replicas: 1 + template: + metadata: + labels: + name: schedule-deployment + spec: + containers: + - name: microservice-schedule + image: microservice-schedule:latest +# env: +# - name: EXTERNAL_IP_ADDR +# valueFrom: +# configMapKeyRef: +# name: ipaddr-config +# key: EXTERNAL_IP_ADDR + ports: + - containerPort: 9080 + imagePullPolicy: Never + volumeMounts: + - name: keystore + mountPath: /etc/wlp/config/keystore + - name: truststore + mountPath: /etc/wlp/config/truststore + - name: liberty-config + mountPath: /config/configDropins + imagePullPolicy: Never + readinessProbe: + httpGet: + path: /schedule/nessProbe + port: 9080 + volumes: + - name: keystore + secret: + secretName: wlp-keystore + - name: truststore + secret: + secretName: wlp-truststore + - name: liberty-config + configMap: + name: liberty-config + items: + - key: keystore.xml + path: defaults/keystore.xml + - key: logging.xml + path: defaults/logging.xml +--- +apiVersion: v1 +kind: Service +metadata: + name: schedule-service + namespace: default +spec: + ports: + - port: 9080 + selector: + name: schedule-deployment diff --git a/manifests/schedule-ingress.yaml b/manifests/schedule-ingress.yaml new file mode 100755 index 0000000..5012fdc --- /dev/null +++ b/manifests/schedule-ingress.yaml @@ -0,0 +1,15 @@ +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + annotations: + ingress.kubernetes.io/rewrite-target: /schedule + name: schedule-ingress +spec: + rules: + - host: + http: + paths: + - path: /schedule + backend: + serviceName: schedule-service + servicePort: 9080 \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100755 index 0000000..8e10b47 --- /dev/null +++ b/pom.xml @@ -0,0 +1,115 @@ + + + + + 4.0.0 + + sample.microservicebuilder + 1.0.0-SNAPSHOT + microservice-schedule + war + Conference :: Schedule + + + 1.8 + 1.8 + artifacts + + + + + + jitpack.io + https://jitpack.io + + + + + + + org.apache.maven.plugins + maven-war-plugin + 2.6 + + ${webxml.path} + false + pom.xml + + + + + io.fabric8 + docker-maven-plugin + + + + microservice-schedule + + ${docker.file.dir} + + artifact + + + + + + + + + + + + + javax + javaee-api + provided + 7.0 + + + + com.fasterxml.jackson.core + jackson-annotations + 2.8.2 + provided + + + + com.github.wasdev.microprofile-conference + demo-bootstrap + 1.0.0 + + + + org.wildfly.swarm + microprofile + provided + 2016.10.0 + + + + + + security + + artifactsSecured + src/main/liberty/webapp-security/web.xml + + + + diff --git a/server.xml b/server.xml new file mode 100755 index 0000000..588470f --- /dev/null +++ b/server.xml @@ -0,0 +1,15 @@ + + + + + microProfile-1.0 + + + + + + + diff --git a/src/main/docker/artifactsSecured/Dockerfile b/src/main/docker/artifactsSecured/Dockerfile new file mode 100755 index 0000000..ac336e5 --- /dev/null +++ b/src/main/docker/artifactsSecured/Dockerfile @@ -0,0 +1,4 @@ +FROM websphere-liberty:microProfile +RUN installUtility install --acceptLicense logstashCollector-1.0 openidConnectClient-1.0 jsp-2.3 ssl-1.0 appSecurity-2.0 +COPY server.xml /config/server.xml +COPY maven/microservice-schedule-1.0.0-SNAPSHOT.war /config/apps/schedule.war diff --git a/src/main/docker/artifactsSecured/server.xml b/src/main/docker/artifactsSecured/server.xml new file mode 100755 index 0000000..c738e3b --- /dev/null +++ b/src/main/docker/artifactsSecured/server.xml @@ -0,0 +1,46 @@ + + + + + ssl-1.0 + appSecurity-2.0 + microProfile-1.0 + jsp-2.3 + openidConnectClient-1.0 + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/io/microprofile/showcase/schedule/CORSFilter.java b/src/main/java/io/microprofile/showcase/schedule/CORSFilter.java new file mode 100755 index 0000000..a34aba4 --- /dev/null +++ b/src/main/java/io/microprofile/showcase/schedule/CORSFilter.java @@ -0,0 +1,23 @@ +package io.microprofile.showcase.schedule; + +import java.io.IOException; + +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.ext.Provider; + +/** + * @author Ken Finnigan + */ +@Provider +public class CORSFilter implements ContainerResponseFilter { + @Override + public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException { + responseContext.getHeaders().add("Access-Control-Allow-Origin", "*"); + responseContext.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization"); + responseContext.getHeaders().add("Access-Control-Allow-Credentials", "true"); + responseContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD"); + responseContext.getHeaders().add("Access-Control-Max-Age", "1209600"); + } +} diff --git a/src/main/java/io/microprofile/showcase/schedule/model/Schedule.java b/src/main/java/io/microprofile/showcase/schedule/model/Schedule.java new file mode 100755 index 0000000..251d6b0 --- /dev/null +++ b/src/main/java/io/microprofile/showcase/schedule/model/Schedule.java @@ -0,0 +1,129 @@ +/* + * Copyright 2016 Microprofile.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.microprofile.showcase.schedule.model; + +import io.microprofile.showcase.schedule.model.adapters.DurationAdapter; +import io.microprofile.showcase.schedule.model.adapters.LocalDateAdapter; +import io.microprofile.showcase.schedule.model.adapters.LocalTimeAdapter; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import java.time.Duration; +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.Objects; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class Schedule { + + private String id; + private String sessionId; + private String venue; + private String venueId; + + @XmlJavaTypeAdapter(LocalDateAdapter.class) + private LocalDate date; + + @XmlJavaTypeAdapter(LocalTimeAdapter.class) + private LocalTime startTime; + + @XmlJavaTypeAdapter(DurationAdapter.class) + private Duration duration; + + public Schedule() { + } + + public Schedule(final String sessionId, final String venue, final String venueId, final LocalDate date, final LocalTime startTime, final Duration duration) { + this(null, sessionId, venue, venueId, date, startTime, duration); + } + + public Schedule(final String id, final String sessionId, final String venue, final String venueId, final LocalDate date, final LocalTime startTime, final Duration duration) { + this.id = id; + this.sessionId = sessionId; + this.venue = venue; + this.venueId = venueId; + this.date = date; + this.startTime = startTime; + this.duration = duration; + } + + public String getId() { + return id; + } + + public void setId(final String id) { + this.id = id; + } + + public String getSessionId() { + return sessionId; + } + + public void setSessionId(final String sessionId) { + this.sessionId = sessionId; + } + + public String getVenue() { + return venue; + } + + public String getVenueId() { + return venueId; + } + + public LocalDate getDate() { + return date; + } + + public LocalTime getStartTime() { + return startTime; + } + + public Duration getDuration() { + return duration; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final Schedule schedule = (Schedule) o; + return Objects.equals(sessionId, schedule.sessionId) && + Objects.equals(venue, schedule.venue) && + Objects.equals(date, schedule.date) && + Objects.equals(startTime, schedule.startTime) && + Objects.equals(duration, schedule.duration); + } + + @Override + public int hashCode() { + return Objects.hash(sessionId, venue, date, startTime, duration); + } + + @Override + public String toString() { + return "Schedule{" + + "session=" + sessionId + + ", venue='" + venue + '\'' + + ", date=" + date + + ", startTime=" + startTime + + ", duration=" + duration + + '}'; + } +} diff --git a/src/main/java/io/microprofile/showcase/schedule/model/adapters/DurationAdapter.java b/src/main/java/io/microprofile/showcase/schedule/model/adapters/DurationAdapter.java new file mode 100755 index 0000000..0b2dc3e --- /dev/null +++ b/src/main/java/io/microprofile/showcase/schedule/model/adapters/DurationAdapter.java @@ -0,0 +1,32 @@ +/* + * Copyright 2016 Microprofile.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.microprofile.showcase.schedule.model.adapters; + +import javax.xml.bind.annotation.adapters.XmlAdapter; +import java.time.Duration; + +public class DurationAdapter extends XmlAdapter { + + @Override + public Duration unmarshal(String v) throws Exception { + return Duration.parse(v); + } + + @Override + public String marshal(Duration v) throws Exception { + return v.toString(); + } +} diff --git a/src/main/java/io/microprofile/showcase/schedule/model/adapters/LocalDateAdapter.java b/src/main/java/io/microprofile/showcase/schedule/model/adapters/LocalDateAdapter.java new file mode 100755 index 0000000..2954eea --- /dev/null +++ b/src/main/java/io/microprofile/showcase/schedule/model/adapters/LocalDateAdapter.java @@ -0,0 +1,32 @@ +/* + * Copyright 2016 Microprofile.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.microprofile.showcase.schedule.model.adapters; + +import javax.xml.bind.annotation.adapters.XmlAdapter; +import java.time.LocalDate; + +public class LocalDateAdapter extends XmlAdapter { + + @Override + public LocalDate unmarshal(String v) throws Exception { + return LocalDate.parse(v); + } + + @Override + public String marshal(LocalDate v) throws Exception { + return v.toString(); + } +} diff --git a/src/main/java/io/microprofile/showcase/schedule/model/adapters/LocalTimeAdapter.java b/src/main/java/io/microprofile/showcase/schedule/model/adapters/LocalTimeAdapter.java new file mode 100755 index 0000000..7824883 --- /dev/null +++ b/src/main/java/io/microprofile/showcase/schedule/model/adapters/LocalTimeAdapter.java @@ -0,0 +1,32 @@ +/* + * Copyright 2016 Microprofile.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.microprofile.showcase.schedule.model.adapters; + +import javax.xml.bind.annotation.adapters.XmlAdapter; +import java.time.LocalTime; + +public class LocalTimeAdapter extends XmlAdapter { + + @Override + public LocalTime unmarshal(String v) throws Exception { + return LocalTime.parse(v); + } + + @Override + public String marshal(LocalTime v) throws Exception { + return v.toString(); + } +} diff --git a/src/main/java/io/microprofile/showcase/schedule/persistence/ScheduleDAO.java b/src/main/java/io/microprofile/showcase/schedule/persistence/ScheduleDAO.java new file mode 100755 index 0000000..d582a18 --- /dev/null +++ b/src/main/java/io/microprofile/showcase/schedule/persistence/ScheduleDAO.java @@ -0,0 +1,148 @@ +/* + * Copyright 2016 Microprofile.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.microprofile.showcase.schedule.persistence; + +import io.microprofile.showcase.bootstrap.BootstrapData; +import io.microprofile.showcase.schedule.model.Schedule; +import io.microprofile.showcase.schedule.model.adapters.LocalDateAdapter; +import io.microprofile.showcase.schedule.model.adapters.LocalTimeAdapter; + +import javax.annotation.PostConstruct; +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import java.time.Duration; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +@ApplicationScoped +public class ScheduleDAO { + + + @Inject + BootstrapData bootstrapData; + + private final AtomicInteger sequence = new AtomicInteger(0); + + private final Map scheduleMap = new ConcurrentHashMap<>(); + private final Map venues = new ConcurrentHashMap<>(); + + @PostConstruct + private void initStore() { + Logger.getLogger(ScheduleDAO.class.getName()).log(Level.INFO, "Initialise schedule DAO from bootstrap data"); + + final LocalDateAdapter dateAdapter = new LocalDateAdapter(); + final LocalTimeAdapter timeAdapter = new LocalTimeAdapter(); + + bootstrapData.getSchedules() + .forEach(bootstrap -> { + + try { + + String venueId = null; + for (final String key : venues.keySet()) { + final String v = venues.get(key); + if (v.equals(bootstrap.getVenue())) { + // existing venue + venueId = key; + break; + } + } + + // generate a new key + if (null == venueId) + venueId = String.valueOf(sequence.incrementAndGet()); + + final Schedule sched = new Schedule( + bootstrap.getId(), + bootstrap.getSessionId(), + bootstrap.getVenue(), + venueId, + dateAdapter.unmarshal(bootstrap.getDate()), + timeAdapter.unmarshal(bootstrap.getStartTime()), + Duration.ofMinutes(new Double(bootstrap.getLength()).longValue()) + ); + + + scheduleMap.put(bootstrap.getId(), sched); + venues.put(venueId, sched.getVenue()); + + } catch (final Exception e) { + System.out.println("Failed to parse bootstrap data: " + e.getMessage()); + } + + }); + + } + + public Schedule addSchedule(final Schedule schedule) { + + final String id = String.valueOf(sequence.incrementAndGet()); + schedule.setId(id); + + if (schedule.getSessionId() == null) { + schedule.setSessionId(String.valueOf(sequence.incrementAndGet())); + } + + scheduleMap.put(id, schedule); + + return schedule; + } + + public List getAllSchedules() { + return new ArrayList<>(scheduleMap.values()); + } + + public Optional findById(final String id) { + return Optional.ofNullable(scheduleMap.get(id)); + } + + public Schedule updateSchedule(final Schedule schedule) { + if (schedule.getId() == null) { + return addSchedule(schedule); + } + + scheduleMap.put(schedule.getId(), schedule); + return schedule; + } + + public void deleteSchedule(final String scheduleId) { + if (scheduleId != null) { + scheduleMap.remove(scheduleId); + } + } + + public List findByVenue(final String venueId) { + return scheduleMap.values() + .stream() + .filter(schedule -> schedule.getVenueId().equals(venueId)) + .collect(Collectors.toList()); + } + + public List findByDate(final LocalDate date) { + return scheduleMap.values() + .stream() + .filter(schedule -> schedule.getDate().equals(date)) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/io/microprofile/showcase/schedule/resources/ScheduleResource.java b/src/main/java/io/microprofile/showcase/schedule/resources/ScheduleResource.java new file mode 100755 index 0000000..ad98255 --- /dev/null +++ b/src/main/java/io/microprofile/showcase/schedule/resources/ScheduleResource.java @@ -0,0 +1,132 @@ +/* + * Copyright 2016 Microprofile.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.microprofile.showcase.schedule.resources; + +import java.net.URI; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.Calendar; +import java.util.List; +import java.util.stream.Collectors; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.GenericEntity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import io.microprofile.showcase.schedule.model.Schedule; +import io.microprofile.showcase.schedule.persistence.ScheduleDAO; + + +@ApplicationScoped +@Produces({MediaType.APPLICATION_JSON}) +@Consumes(MediaType.APPLICATION_JSON) +@Path("/") +public class ScheduleResource { + + @Inject + private ScheduleDAO scheduleDAO; + + @POST + public Response add(final Schedule schedule) { + final Schedule created = scheduleDAO.addSchedule(schedule); + return Response.created(URI.create("/" + created.getId())) + .entity(created) + .build(); + } + + // For use as a k8s readinessProbe for this service + @GET + @Path("/nessProbe") + @Produces(MediaType.TEXT_PLAIN) + public Response nessProbe() throws Exception { + + return Response.ok("schedule ready at " + Calendar.getInstance().getTime()).build(); + } + + @GET + @Path("/{id}") + public Response retrieve(@PathParam("id") final String id) { + return scheduleDAO.findById(id) + .map(schedule -> Response.ok(schedule).build()) + .orElse(Response.status(Response.Status.NOT_FOUND).build()); + } + + @GET + @Path("/all") + public Response allSchedules() { + final List allSchedules = scheduleDAO.getAllSchedules(); + final GenericEntity> entity = buildEntity(allSchedules); + return Response.ok(entity).build(); + } + + @GET + @Path("/venue/{id}") + public Response allForVenue(@PathParam("id") final String id) { + final List schedulesByVenue = scheduleDAO.findByVenue(id); + final GenericEntity> entity = buildEntity(schedulesByVenue); + return Response.ok(entity).build(); + } + + @GET + @Path("/active/{dateTime}") + public Response activeAtDate(@PathParam("dateTime") final String dateTimeString) { + final LocalDateTime dateTime = LocalDateTime.parse(dateTimeString); + final List schedulesByDate = scheduleDAO.findByDate(dateTime.toLocalDate()); + final List activeAtTime = schedulesByDate.stream() + .filter(schedule -> isTimeInSchedule(dateTime.toLocalTime(), schedule)) + .collect(Collectors.toList()); + final GenericEntity> entity = buildEntity(activeAtTime); + return Response.ok(entity).build(); + } + + @GET + @Path("/all/{date}") + public Response allForDay(@PathParam("date") final String dateString) { + final LocalDate date = LocalDate.parse(dateString); + final List schedulesByDate = scheduleDAO.findByDate(date); + final GenericEntity> entity = buildEntity(schedulesByDate); + return Response.ok(entity).build(); + } + + @DELETE + @Path("/{scheduleId}") + public Response remove(@PathParam("scheduleId") final String scheduleId) { + scheduleDAO.deleteSchedule(scheduleId); + return Response.noContent().build(); + } + + private GenericEntity> buildEntity(final List scheduleList) { + return new GenericEntity>(scheduleList) { + }; + } + + private boolean isTimeInSchedule(final LocalTime currentTime, final Schedule schedule) { + final LocalTime scheduleStartTime = schedule.getStartTime(); + final LocalTime scheduleEndTime = scheduleStartTime.plus(schedule.getDuration()); + return scheduleStartTime.isBefore(currentTime) && + scheduleEndTime.isAfter(currentTime); + } +} diff --git a/src/main/java/io/microprofile/showcase/schedule/rest/Application.java b/src/main/java/io/microprofile/showcase/schedule/rest/Application.java new file mode 100755 index 0000000..973c58e --- /dev/null +++ b/src/main/java/io/microprofile/showcase/schedule/rest/Application.java @@ -0,0 +1,23 @@ +/* + * Copyright 2016 Microprofile.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.microprofile.showcase.schedule.rest; + +import javax.ws.rs.ApplicationPath; + +@ApplicationPath("/schedule") +public class Application extends javax.ws.rs.core.Application { + +} diff --git a/src/main/liberty/webapp-security/web.xml b/src/main/liberty/webapp-security/web.xml new file mode 100755 index 0000000..210af0a --- /dev/null +++ b/src/main/liberty/webapp-security/web.xml @@ -0,0 +1,34 @@ + + + + Schedule REST resource + + + DefaultSecurityConstraints + + /* + + + NONE + + + ScheduleRole + + + diff --git a/src/test/java/io/microprofile/showcase/schedule/DeleteMeTest.java b/src/test/java/io/microprofile/showcase/schedule/DeleteMeTest.java new file mode 100755 index 0000000..6eea8a5 --- /dev/null +++ b/src/test/java/io/microprofile/showcase/schedule/DeleteMeTest.java @@ -0,0 +1,21 @@ +/* + * Copyright 2016 Microprofile.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.microprofile.showcase.schedule; + + +public class DeleteMeTest { + +} \ No newline at end of file