Move Spring Boot Actuator Sample under the spring-geode-samples.

Declare the FreeFair Lombok Gradle Plugin in spring-geode-samples-boot-actuator.gradle.
This commit is contained in:
John Blum
2019-04-28 19:08:56 -07:00
parent 12a675e045
commit 280ee00f61
15 changed files with 18 additions and 7 deletions

View File

@@ -0,0 +1,29 @@
plugins {
id "io.freefair.lombok" version "3.2.1"
}
apply plugin: 'io.spring.convention.spring-sample-boot'
description = "Spring Geode Sample demonstrating the use of Spring Boot Actuator with Apache Geode."
dependencies {
compile project(":spring-geode-starter-actuator")
compile ("org.springframework.boot:spring-boot-starter-web") {
exclude group: "org.springframework.boot", module: "spring-boot-starter-logging"
}
compile "org.springframework.data:spring-data-geode-test"
runtime "org.springframework.shell:spring-shell"
runtime ("org.springframework.boot:spring-boot-starter-jetty") {
exclude group: "org.springframework.boot", module: "spring-boot-starter-logging"
}
}
bootJar {
mainClassName = 'example.app.temp.geode.client.BootGeodeClientApplication'
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2018 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 example.app.temp.event;
import example.app.temp.model.TemperatureReading;
@SuppressWarnings("unused")
public class BoilingTemperatureEvent extends TemperatureEvent {
public BoilingTemperatureEvent(Object source, TemperatureReading temperatureReading) {
super(source, temperatureReading);
}
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2018 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 example.app.temp.event;
import example.app.temp.model.TemperatureReading;
@SuppressWarnings("unused")
public class FreezingTemperatureEvent extends TemperatureEvent {
public FreezingTemperatureEvent(Object source, TemperatureReading temperatureReading) {
super(source, temperatureReading);
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2018 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 example.app.temp.event;
import lombok.Getter;
import org.springframework.context.ApplicationEvent;
import example.app.temp.model.TemperatureReading;
public class TemperatureEvent extends ApplicationEvent {
@Getter
private final TemperatureReading temperatureReading;
public TemperatureEvent(Object source, TemperatureReading temperatureReading) {
super(source);
this.temperatureReading = temperatureReading;
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright 2018 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 example.app.temp.geode.client;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.event.EventListener;
import org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions;
import org.springframework.geode.config.annotation.UseGroups;
import org.springframework.geode.config.annotation.UseMemberName;
import example.app.temp.event.BoilingTemperatureEvent;
import example.app.temp.event.FreezingTemperatureEvent;
import example.app.temp.event.TemperatureEvent;
import example.app.temp.model.TemperatureReading;
import example.app.temp.service.TemperatureMonitor;
@SpringBootApplication
@EnableEntityDefinedRegions(basePackageClasses = TemperatureReading.class)
@UseGroups("TemperatureMonitors")
@UseMemberName("TemperatureMonitoringService")
@SuppressWarnings("unused")
public class BootGeodeClientApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(BootGeodeClientApplication.class)
.web(WebApplicationType.SERVLET)
.build()
.run(args);
}
@Bean
TemperatureMonitor temperatureMonitor(ApplicationEventPublisher applicationEventPublisher) {
return new TemperatureMonitor(applicationEventPublisher);
}
@EventListener(classes = { BoilingTemperatureEvent.class, FreezingTemperatureEvent.class })
public void temperatureEventHandler(TemperatureEvent temperatureEvent) {
System.err.printf("%1$s TEMPERATURE READING [%2$s]%n",
temperatureEvent instanceof BoilingTemperatureEvent ? "HOT" : "COLD",
temperatureEvent.getTemperatureReading());
}
}

View File

@@ -0,0 +1,106 @@
/*
* Copyright 2018 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 example.app.temp.geode.server;
import java.util.Optional;
import org.apache.geode.cache.GemFireCache;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
import org.springframework.data.gemfire.IndexFactoryBean;
import org.springframework.data.gemfire.RegionFactoryBean;
import org.springframework.data.gemfire.config.annotation.CacheServerApplication;
import org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions;
import org.springframework.data.gemfire.config.annotation.EnableStatistics;
import org.springframework.data.gemfire.config.annotation.RegionConfigurer;
import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;
import org.springframework.geode.config.annotation.UseGroups;
import org.springframework.scheduling.annotation.EnableScheduling;
import example.app.temp.model.TemperatureReading;
import example.app.temp.repo.TemperatureReadingRepository;
import example.app.temp.service.TemperatureSensor;
@SpringBootApplication
@CacheServerApplication(name = "TemperatureServiceServer")
@EnableEntityDefinedRegions(basePackageClasses = TemperatureReading.class)
@EnableGemfireRepositories(basePackageClasses = TemperatureReadingRepository.class)
@EnableScheduling
@EnableStatistics
@UseGroups("TemperatureSensors")
@SuppressWarnings("unused")
public class BootGeodeServerApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(BootGeodeServerApplication.class)
.web(WebApplicationType.SERVLET)
.build()
.run(args);
}
@Bean
TemperatureSensor temperatureSensor(TemperatureReadingRepository repository) {
return new TemperatureSensor(repository);
}
@Bean
RegionConfigurer temperatureReadingsConfigurer() {
return new RegionConfigurer() {
@Override
public void configure(String beanName, RegionFactoryBean<?, ?> regionBean) {
Optional.ofNullable(beanName)
.filter("TemperatureReadings"::equals)
.ifPresent(it -> regionBean.setStatisticsEnabled(true));
}
};
}
@Bean
@DependsOn("TemperatureReadings")
IndexFactoryBean temperatureReadingTemperatureIndex(GemFireCache gemfireCache) {
IndexFactoryBean temperatureTimestampIndex = new IndexFactoryBean();
temperatureTimestampIndex.setCache(gemfireCache);
temperatureTimestampIndex.setExpression("temperature");
temperatureTimestampIndex.setFrom("/TemperatureReadings");
temperatureTimestampIndex.setName("TemperatureReadingTemperatureIdx");
return temperatureTimestampIndex;
}
@Bean
@DependsOn("TemperatureReadings")
IndexFactoryBean temperatureReadingTimestampIndex(GemFireCache gemfireCache) {
IndexFactoryBean temperatureTimestampIndex = new IndexFactoryBean();
temperatureTimestampIndex.setCache(gemfireCache);
temperatureTimestampIndex.setExpression("timestamp");
temperatureTimestampIndex.setFrom("/TemperatureReadings");
temperatureTimestampIndex.setName("TemperatureReadingTimestampIdx");
return temperatureTimestampIndex;
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2018 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 example.app.temp.model;
import lombok.Data;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.gemfire.mapping.annotation.Region;
@Data
@Region("TemperatureReadings")
@RequiredArgsConstructor(staticName = "newTemperatureReading")
@SuppressWarnings("unused")
public class TemperatureReading {
private static final int BOILING_TEMPERATURE = 212;
private static final int FREEZING_TEMPERATURE = 32;
@Id
private Long timestamp = System.currentTimeMillis();
@NonNull
private Integer temperature;
@Transient
public boolean isBoiling() {
Integer temperature = getTemperature();
return temperature != null && temperature >= BOILING_TEMPERATURE;
}
@Transient
public boolean isNormal() {
return !(isBoiling() || isFreezing());
}
@Transient
public boolean isFreezing() {
Integer temperature = getTemperature();
return temperature != null && temperature <= FREEZING_TEMPERATURE;
}
@Override
public String toString() {
return String.format("%d °F", getTemperature());
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2018 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 example.app.temp.repo;
import java.util.List;
import org.springframework.data.gemfire.repository.Query;
import org.springframework.data.repository.CrudRepository;
import example.app.temp.model.TemperatureReading;
@SuppressWarnings("unused")
public interface TemperatureReadingRepository extends CrudRepository<TemperatureReading, Long> {
List<TemperatureReading> findByTimestampGreaterThanAndTimestampLessThan(Long timestampLowerBound,
Long timestampUpperBound);
@Query("SELECT count(*) FROM /TemperatureReadings WHERE temperature >= 212")
Integer countBoilingTemperatureReadings();
@Query("SELECT count(*) FROM /TemperatureReadings WHERE temperature <= 32")
Integer countFreezingTemperatureReadings();
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2018 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 example.app.temp.service;
import java.util.Optional;
import org.apache.geode.cache.query.CqEvent;
import org.apache.shiro.util.Assert;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.gemfire.listener.annotation.ContinuousQuery;
import org.springframework.stereotype.Service;
import example.app.temp.event.BoilingTemperatureEvent;
import example.app.temp.event.FreezingTemperatureEvent;
import example.app.temp.model.TemperatureReading;
@Service
@SuppressWarnings("unused")
public class TemperatureMonitor {
private final ApplicationEventPublisher applicationEventPublisher;
public TemperatureMonitor(ApplicationEventPublisher applicationEventPublisher) {
Assert.notNull(applicationEventPublisher, "ApplicationEventPublisher is required");
this.applicationEventPublisher = applicationEventPublisher;
}
@ContinuousQuery(name = "BoilingTemperatureMonitor",
query = "SELECT * FROM /TemperatureReadings WHERE temperature >= 212")
public void boilingTemperatureReadings(CqEvent event) {
Optional.ofNullable(event)
.map(CqEvent::getNewValue)
.filter(TemperatureReading.class::isInstance)
.map(TemperatureReading.class::cast)
.map(it -> new BoilingTemperatureEvent(this, it))
.ifPresent(this.applicationEventPublisher::publishEvent);
}
@ContinuousQuery(name = "FreezingTemperatureMonitor",
query = "SELECT * FROM /TemperatureReadings WHERE temperature <= 32")
public void freezingTemperatureReadings(CqEvent event) {
Optional.ofNullable(event)
.map(CqEvent::getNewValue)
.filter(TemperatureReading.class::isInstance)
.map(TemperatureReading.class::cast)
.map(it -> new FreezingTemperatureEvent(this, it))
.ifPresent(this.applicationEventPublisher::publishEvent);
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2018 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 example.app.temp.service;
import java.io.PrintStream;
import java.util.PrimitiveIterator;
import java.util.Random;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import example.app.temp.model.TemperatureReading;
import example.app.temp.repo.TemperatureReadingRepository;
@Service
@SuppressWarnings("unused")
public class TemperatureSensor {
private final PrimitiveIterator.OfInt temperatureStream = new Random(System.currentTimeMillis())
.ints(-100, 400).iterator();
private final TemperatureReadingRepository repository;
public TemperatureSensor(TemperatureReadingRepository repository) {
Assert.notNull(repository, "TemperatureReadingRepository is required");
this.repository = repository;
}
@Scheduled(fixedRateString = "${example.app.temp.sensor.reading.schedule.rate:1000}")
public void readTemperature() {
this.repository.save(log(TemperatureReading.newTemperatureReading(temperatureStream.nextInt())));
}
private TemperatureReading log(TemperatureReading temperatureReading) {
PrintStream out = temperatureReading.isNormal() ? System.out : System.err;
out.printf("TEMPERATURE READING [%s]%n", temperatureReading);
return temperatureReading;
}
}

View File

@@ -0,0 +1,3 @@
# Temperature Service client application configuration properties
server.port=9191

View File

@@ -0,0 +1,3 @@
# Temperature Service server application configuration properties
server.port=8181

View File

@@ -0,0 +1,5 @@
# Temperature Service application configuration properties
management.endpoint.health.show-details=always
#management.endpoints.web.exposure.include=env
spring.data.gemfire.cache.log-level=error