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