diff --git a/src/tamagotchi-service/pom.xml b/src/tamagotchi-service/pom.xml index 0d9d8fd..d130b8b 100644 --- a/src/tamagotchi-service/pom.xml +++ b/src/tamagotchi-service/pom.xml @@ -19,6 +19,18 @@ 2.1.6.RELEASE + + + + com.google.cloud + libraries-bom + 2.9.0 + pom + import + + + + org.springframework.boot @@ -29,6 +41,10 @@ spring-boot-starter-test test + + com.google.cloud + google-cloud-pubsub + com.jayway.jsonpath json-path diff --git a/src/tamagotchi-service/src/main/java/hello/Application.java b/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/Application.java similarity index 90% rename from src/tamagotchi-service/src/main/java/hello/Application.java rename to src/tamagotchi-service/src/main/java/com/sap/tamagotchi/Application.java index 2eaac3d..5c4e423 100644 --- a/src/tamagotchi-service/src/main/java/hello/Application.java +++ b/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/Application.java @@ -1,4 +1,4 @@ -package hello; +package com.sap.tamagotchi; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/controller/DeviceController.java b/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/controller/DeviceController.java new file mode 100644 index 0000000..4866888 --- /dev/null +++ b/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/controller/DeviceController.java @@ -0,0 +1,28 @@ +package com.sap.tamagotchi.controller; + +import java.util.concurrent.atomic.AtomicLong; + +import com.sap.tamagotchi.model.Device; +import com.sap.tamagotchi.publisher.PublisherService; +import com.sap.tamagotchi.service.TamagotchiService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class DeviceController { + + private static final String template = "Hello, %s!"; + private final AtomicLong counter = new AtomicLong(); + private final TamagotchiService tamagotchiService; + + @Autowired + public DeviceController(TamagotchiService tamagotchiService) { + this.tamagotchiService = tamagotchiService; + } + + @RequestMapping("devices/{deviceId}") + public Device getDevice(String deviceId) { + return tamagotchiService.getDevice(deviceId); + } +} diff --git a/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/model/Device.java b/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/model/Device.java new file mode 100644 index 0000000..d224687 --- /dev/null +++ b/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/model/Device.java @@ -0,0 +1,4 @@ +package com.sap.tamagotchi.model; + +public class Device { +} diff --git a/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/model/DeviceEvent.java b/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/model/DeviceEvent.java new file mode 100644 index 0000000..561b2e0 --- /dev/null +++ b/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/model/DeviceEvent.java @@ -0,0 +1,4 @@ +package com.sap.tamagotchi.model; + +public class DeviceEvent { +} diff --git a/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/model/DummyMessage.java b/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/model/DummyMessage.java new file mode 100644 index 0000000..b717b70 --- /dev/null +++ b/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/model/DummyMessage.java @@ -0,0 +1,13 @@ +package com.sap.tamagotchi.model; + +public class DummyMessage { + private final String message; + + public DummyMessage(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } +} diff --git a/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/model/IoTMessage.java b/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/model/IoTMessage.java new file mode 100644 index 0000000..f0acb0d --- /dev/null +++ b/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/model/IoTMessage.java @@ -0,0 +1,7 @@ +package com.sap.tamagotchi.model; + +public interface IoTMessage { + String toMessage(); + + String getTopic(); +} diff --git a/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/publisher/PublisherService.java b/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/publisher/PublisherService.java new file mode 100644 index 0000000..a05a399 --- /dev/null +++ b/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/publisher/PublisherService.java @@ -0,0 +1,71 @@ +package com.sap.tamagotchi.publisher; + + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.api.core.ApiFuture; +import com.google.api.core.ApiFutures; +import com.google.cloud.ServiceOptions; +import com.google.cloud.pubsub.v1.Publisher; +import com.google.protobuf.ByteString; +import com.google.pubsub.v1.ProjectTopicName; +import com.google.pubsub.v1.PubsubMessage; +import com.sap.tamagotchi.model.DummyMessage; +import com.sap.tamagotchi.model.IoTMessage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.lang.invoke.MethodHandles; +import java.util.ArrayList; +import java.util.List; + +@Service +public class PublisherService { + + private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + private static final ObjectMapper mapper = new ObjectMapper(); + + // use the default project id + private static final String PROJECT_ID = ServiceOptions.getDefaultProjectId(); + + public void publish(IoTMessage message) throws Exception { + String topicId = message.getTopic(); + ProjectTopicName topicName = ProjectTopicName.of(PROJECT_ID, topicId); + Publisher publisher = null; + List> futures = new ArrayList<>(); + + try { + // Create a publisher instance with default settings bound to the topic + publisher = Publisher.newBuilder(topicName).build(); + LOGGER.info("publish to topic" + publisher.getTopicNameString()); + + // convert message to bytes + ByteString data = ByteString.copyFromUtf8(message.toMessage()); + PubsubMessage pubsubMessage = PubsubMessage.newBuilder() + .setData(data) + .build(); + LOGGER.info("publish to message" + message.toMessage()); + + // Schedule a message to be published. Messages are automatically batched. + ApiFuture future = publisher.publish(pubsubMessage); + futures.add(future); + + } finally { + // Wait on any pending requests + List messageIds = ApiFutures.allAsList(futures).get(); + + for (String messageId : messageIds) { + System.out.println(messageId); + LOGGER.info("publish successful : " + messageId); + } + + if (publisher != null) { + // When finished with the publisher, shutdown to free up resources. + publisher.shutdown(); + } + + if (messageIds.isEmpty()) + LOGGER.info("no messages published "); + } + } +} diff --git a/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/service/TamagotchiService.java b/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/service/TamagotchiService.java new file mode 100644 index 0000000..b4c7371 --- /dev/null +++ b/src/tamagotchi-service/src/main/java/com/sap/tamagotchi/service/TamagotchiService.java @@ -0,0 +1,22 @@ +package com.sap.tamagotchi.service; + +import com.sap.tamagotchi.model.Device; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +@Service +public class TamagotchiService { + + private final Map deviceRegistry = new HashMap<>(); + + public Device getDevice(String deviceId) { + return deviceRegistry.get(deviceId); + } + + public Collection getDevices() { + return deviceRegistry.values(); + } +} diff --git a/src/tamagotchi-service/src/main/java/hello/Greeting.java b/src/tamagotchi-service/src/main/java/hello/Greeting.java deleted file mode 100644 index 5d10b59..0000000 --- a/src/tamagotchi-service/src/main/java/hello/Greeting.java +++ /dev/null @@ -1,20 +0,0 @@ -package hello; - -public class Greeting { - - private final long id; - private final String content; - - public Greeting(long id, String content) { - this.id = id; - this.content = content; - } - - public long getId() { - return id; - } - - public String getContent() { - return content; - } -} diff --git a/src/tamagotchi-service/src/main/java/hello/GreetingController.java b/src/tamagotchi-service/src/main/java/hello/GreetingController.java deleted file mode 100644 index e356ab2..0000000 --- a/src/tamagotchi-service/src/main/java/hello/GreetingController.java +++ /dev/null @@ -1,19 +0,0 @@ -package hello; - -import java.util.concurrent.atomic.AtomicLong; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class GreetingController { - - private static final String template = "Hello, %s!"; - private final AtomicLong counter = new AtomicLong(); - - @RequestMapping("/greeting") - public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) { - return new Greeting(counter.incrementAndGet(), - String.format(template, name)); - } -} diff --git a/src/tamagotchi-service/src/test/java/hello/GreetingControllerTests.java b/src/tamagotchi-service/src/test/java/hello/GreetingControllerTests.java deleted file mode 100644 index 4a3c64b..0000000 --- a/src/tamagotchi-service/src/test/java/hello/GreetingControllerTests.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2016 the original author or authors. - * - * 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 - * - * https://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 hello; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; - -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureMockMvc -public class GreetingControllerTests { - - @Autowired - private MockMvc mockMvc; - - @Test - public void noParamGreetingShouldReturnDefaultMessage() throws Exception { - - this.mockMvc.perform(get("/greeting")).andDo(print()).andExpect(status().isOk()) - .andExpect(jsonPath("$.content").value("Hello, World!")); - } - - @Test - public void paramGreetingShouldReturnTailoredMessage() throws Exception { - - this.mockMvc.perform(get("/greeting").param("name", "Spring Community")) - .andDo(print()).andExpect(status().isOk()) - .andExpect(jsonPath("$.content").value("Hello, Spring Community!")); - } - -}