diff --git a/crud.iml b/crud.iml
index d935a7b..add7feb 100644
--- a/crud.iml
+++ b/crud.iml
@@ -13,16 +13,19 @@
-
+
+
+ file://$MODULE_DIR$/src/main/java/com/example/crud/ApplicationConfig.java
+ file://$MODULE_DIR$/src/main/java/com/example/crud/CacheConfiguration.java
+ file://$MODULE_DIR$/src/main/java/com/example/crud/EhCacheConfiguration.java
+ file://$MODULE_DIR$/src/main/java/com/example/crud/metrics/MetricsConfiguration.java
+ file://$MODULE_DIR$/src/main/java/com/example/crud/metrics/SpringConfiguringClass.java
+ file://$MODULE_DIR$/applicationContext.xml
+
+
-
-
-
+
@@ -55,7 +58,6 @@
-
@@ -67,25 +69,21 @@
+
-
-
-
-
-
-
-
-
-
-
+
+
-
+
+
+
+
@@ -102,10 +100,22 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 77f17f8..7bf786f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,6 +16,7 @@
${java.version}
[5.1.0-m3, 5.9)
1.8.10
+ 3.2.2
5.0.0.M5
Kay-M4
@@ -29,6 +30,14 @@
false
+
+ clojars.org
+ http://clojars.org/repo
+
+
+ maven.apache.org
+ http://repo.maven.apache.org/maven2/
+
@@ -116,13 +125,26 @@
3.2.0
+
+ org.hdrhistogram
+ HdrHistogram
+ [2.1.8,)
+
+
org.datanucleus
datanucleus-cache
5.0.0-release
+
-
-
- org.infinispan
- infinispan-embedded
- 9.0.2.Final
-
-
- org.jboss.slf4j
- slf4j-jboss-logging
-
-
- org.slf4j
- slf4j-log4j12
-
-
- log4j
- log4j
-
-
-
-
-
- org.infinispan
- infinispan-jcache
- 9.0.2.Final
-
-
javax.cache
cache-api
1.0.0
+
-
+
+ net.sf.ehcache
+ ehcache-core
+ 2.6.11
+
+
+
+ net.sf.ehcache
+ ehcache
+ 2.10.4
+ pom
+
+
+
+ net.sf.ehcache
+ ehcache-jgroupsreplication
+ 1.7
+
@@ -207,6 +205,12 @@
${spring.version}
+
+ org.springframework
+ spring-context-support
+ ${spring.version}
+
+
org.springframework.data
spring-data-jpa
@@ -264,6 +268,67 @@
test
+
+
+ io.dropwizard.metrics
+ metrics-core
+ ${metrics.version}
+
+
+
+
+
+ io.dropwizard.metrics
+ metrics-logback
+ 3.2.2
+
+
+
+ io.dropwizard.metrics
+ metrics-jvm
+ ${metrics.version}
+
+
+
+
+ io.dropwizard.metrics
+ metrics-healthchecks
+ ${metrics.version}
+
+
+
+
+ io.dropwizard.metrics
+ metrics-graphite
+ ${metrics.version}
+
+
+
+
+ com.ryantenney.metrics
+ metrics-spring
+ 3.1.3
+
+
+
+ io.riemann
+ metrics3-riemann-reporter
+ 0.4.5
+
+
+
+ defunkt
+ logback-riemann-appender
+ 0.4.0
+
+
+
+
+
+ javax.inject
+ javax.inject
+ 1
+
@@ -306,12 +378,12 @@
aspectj-maven-plugin
1.10
-
+
diff --git a/src/main/java/com/example/crud/ApplicationConfig.java b/src/main/java/com/example/crud/ApplicationConfiguration.java
similarity index 52%
rename from src/main/java/com/example/crud/ApplicationConfig.java
rename to src/main/java/com/example/crud/ApplicationConfiguration.java
index a616a5d..97c3c41 100644
--- a/src/main/java/com/example/crud/ApplicationConfig.java
+++ b/src/main/java/com/example/crud/ApplicationConfiguration.java
@@ -1,15 +1,14 @@
package com.example.crud;
+import com.datastax.driver.core.Cluster;
+import com.datastax.driver.core.Session;
import com.example.crud.entities.AbstractAuditableEntity;
import com.example.crud.entities.AbstractEntity;
import com.example.crud.entities.Product;
+import org.datanucleus.ExecutionContext;
import org.datanucleus.enhancer.DataNucleusEnhancer;
-import org.infinispan.configuration.cache.CacheMode;
-import org.infinispan.configuration.cache.ConfigurationBuilder;
-import org.infinispan.configuration.global.GlobalConfigurationBuilder;
-import org.infinispan.manager.DefaultCacheManager;
-import org.infinispan.manager.EmbeddedCacheManager;
-import org.springframework.cache.annotation.EnableCaching;
+import org.datanucleus.store.StoreManager;
+import org.datanucleus.store.connection.ManagedConnection;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@@ -22,18 +21,17 @@ import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.annotation.PostConstruct;
+import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
-import java.net.UnknownHostException;
@Configuration
@EnableJpaRepositories
@EnableJpaAuditing
@EnableScheduling
@EnableAspectJAutoProxy
-@EnableCaching
@EnableTransactionManagement
-class ApplicationConfig {
+class ApplicationConfiguration {
@PostConstruct
private void enhanceModelObjectBytecode() {
@@ -60,43 +58,30 @@ class ApplicationConfig {
return txManager;
}
- @Bean
- public EmbeddedCacheManager cacheManager() {
- return infinispanEmbeddedDistributedCacheManager();
- }
-
+ // Auditing
@Bean
public AuditorAware auditorAware() {
return new UsernameAuditorAware();
}
- private EmbeddedCacheManager infinispanEmbeddedDistributedCacheManager() {
- String nodeName = null;
- try {
- nodeName = java.net.InetAddress.getLocalHost().getHostName();
- } catch (UnknownHostException e) {
- nodeName = "localhost";
- }
-// ConfigurationBuilder cb = new ConfigurationBuilder(); cb.addCluster("HighQCacheCluster").addClusterNode("jboss1ind1", 11222).addClusterNode("udit.local.com", 11222); RemoteCacheManager rmc = new RemoteCacheManager(cb.build());
+ // Cassandra
+ @Bean
+ public EntityManager entityManager() {
+ EntityManager em = entityManagerFactory().createEntityManager();
+ return em;
+ }
- DefaultCacheManager cacheManager = new DefaultCacheManager(
- GlobalConfigurationBuilder.defaultClusteredBuilder()
- .transport().nodeName(nodeName).addProperty("configurationFile",
- "jgroups-l2-cache-udp-largecluster.xml")
- .build(),
- new ConfigurationBuilder()
- .clustering()
- .cacheMode(CacheMode.INVALIDATION_SYNC)
- .build()
- );
- // The only way to get the "repl" cache to be exactly the same as the default cache is to not define it at all
- cacheManager.defineConfiguration("dist", new ConfigurationBuilder()
- .clustering()
- .cacheMode(CacheMode.DIST_SYNC)
- .hash().numOwners(2)
- .build()
- );
- return cacheManager;
+ @Bean
+ public Session session() {
+ StoreManager storeManager = ((ExecutionContext)entityManager().getDelegate()).getNucleusContext().getStoreManager();
+ ManagedConnection connection = storeManager.getConnection(-1);
+ Session session = (Session) connection.getConnection();
+ return session;
+ }
+
+ @Bean
+ public Cluster cluster() {
+ return session().getCluster();
}
}
diff --git a/src/main/java/com/example/crud/CacheClusterListener.java b/src/main/java/com/example/crud/CacheClusterListener.java
deleted file mode 100644
index 5feeb5b..0000000
--- a/src/main/java/com/example/crud/CacheClusterListener.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.example.crud;
-
-import org.infinispan.notifications.Listener;
-import org.infinispan.notifications.cachelistener.annotation.CacheEntryCreated;
-import org.infinispan.notifications.cachelistener.annotation.CacheEntryModified;
-import org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved;
-import org.infinispan.notifications.cachelistener.annotation.TopologyChanged;
-import org.infinispan.notifications.cachelistener.event.CacheEntryCreatedEvent;
-import org.infinispan.notifications.cachelistener.event.CacheEntryModifiedEvent;
-import org.infinispan.notifications.cachelistener.event.CacheEntryRemovedEvent;
-import org.infinispan.notifications.cachelistener.event.TopologyChangedEvent;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-
-@Listener(clustered = true)
-public class CacheClusterListener {
- private Logger log = LoggerFactory.getLogger(getClass().getName());
-
- @CacheEntryCreated
- public void observeAdd(CacheEntryCreatedEvent event) {
- if (event.isPre())
- return;
-
- log.info("Cache entry %s added in cache %s", event.getKey(), event.getCache());
- }
-
- @CacheEntryModified
- public void observeUpdate(CacheEntryModifiedEvent event) {
- if (event.isPre())
- return;
-
- log.info("Cache entry %s = %s modified in cache %s", event.getKey(), event.getValue(), event.getCache());
- }
-
- @CacheEntryRemoved
- public void observeRemove(CacheEntryRemovedEvent event) {
- if (event.isPre())
- return;
-
- log.info("Cache entry %s removed in cache %s", event.getKey(), event.getCache());
- }
-
- @TopologyChanged
- public void observeTopologyChange(TopologyChangedEvent event) {
- if (event.isPre())
- return;
-
- log.info("Cache %s topology changed, new membership is %s", event.getCache().getName(), event.getConsistentHashAtEnd().getMembers());
- }
-
-}
diff --git a/src/main/java/com/example/crud/CacheConfiguration.java b/src/main/java/com/example/crud/CacheConfiguration.java
new file mode 100644
index 0000000..66489ba
--- /dev/null
+++ b/src/main/java/com/example/crud/CacheConfiguration.java
@@ -0,0 +1,135 @@
+package com.example.crud;
+
+import com.google.common.collect.Lists;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.CachingConfigurer;
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.cache.concurrent.ConcurrentMapCache;
+import org.springframework.cache.interceptor.CacheErrorHandler;
+import org.springframework.cache.interceptor.CacheResolver;
+import org.springframework.cache.interceptor.KeyGenerator;
+import org.springframework.cache.support.CompositeCacheManager;
+import org.springframework.cache.support.SimpleCacheManager;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Configuration
+//@ComponentScan("com.example.crud")
+//@PropertySource("application.properties")
+@EnableCaching
+public class CacheConfiguration extends CachingConfigurerSupport {
+
+ //private final CacheProperties cacheProperties;
+
+ //@Autowired
+ //public CacheConfiguration(CacheProperties cacheProperties) {
+// this.cacheProperties = cacheProperties;
+// }
+
+ @Qualifier("ehCacheCacheManager")
+ @Autowired(required = false)
+ private CacheManager ehCacheCacheManager;
+
+ /*
+ @Qualifier("redisCacheManager")
+ @Autowired(required = false)
+ private CacheManager redisCacheManager;
+ */
+
+ @Bean
+ @Override
+ public CacheManager cacheManager() {
+// if (cacheProperties.isEnabled()) {
+
+ List cacheManagers = Lists.newArrayList();
+
+ if (this.ehCacheCacheManager != null) {
+ cacheManagers.add(this.ehCacheCacheManager);
+ }
+
+ /*
+ if (this.redisCacheManager != null) {
+ cacheManagers.add(this.redisCacheManager);
+ }
+ */
+
+ CompositeCacheManager cacheManager = new CompositeCacheManager();
+
+ cacheManager.setCacheManagers(cacheManagers);
+ cacheManager.setFallbackToNoOpCache(false);
+
+ return cacheManager;
+/*
+ } else {
+ SimpleCacheManager cacheManager = new SimpleCacheManager();
+ List caches = cacheProperties.getCacheNameList()
+ .stream()
+ .map(cacheName -> new ConcurrentMapCache(cacheName))
+ .collect(Collectors.toList());
+ cacheManager.setCaches(caches);
+ return cacheManager;
+ }
+*/
+ }
+
+ @Bean
+ @Override
+ public CacheResolver cacheResolver() {
+ return null;
+ }
+
+ @Bean
+ @Override
+ public KeyGenerator keyGenerator() {
+ /* Simplistic KeyGenerator example:
+ return new KeyGenerator() {
+ @Override
+ public Object generate(Object o, Method method, Object... params) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(o.getClass().getName());
+ sb.append(method.getName());
+ for (Object param : params) {
+ sb.append(param.toString());
+ }
+ return sb.toString();
+ }
+ };
+ */
+ // Same logic as the DefaultKeyGenerator
+ return new KeyGenerator() {
+
+ public static final int NO_PARAM_KEY = 0;
+ public static final int NULL_PARAM_KEY = 53;
+
+ public Object generate(Object target, Method method, Object... params) {
+ if (params.length == 1) {
+ return (params[0] == null ? NULL_PARAM_KEY : params[0]);
+ }
+ if (params.length == 0) {
+ return NO_PARAM_KEY;
+ }
+ int hashCode = 17;
+ for (Object object : params) {
+ hashCode = 31 * hashCode + (object == null ? NULL_PARAM_KEY : object.hashCode());
+ }
+ return Integer.valueOf(hashCode);
+ }
+ };
+ }
+
+ @Bean
+ @Override
+ public CacheErrorHandler errorHandler () {
+ return null;
+ }
+
+}
diff --git a/src/main/java/com/example/crud/EhCacheConfiguration.java b/src/main/java/com/example/crud/EhCacheConfiguration.java
new file mode 100644
index 0000000..7fda79a
--- /dev/null
+++ b/src/main/java/com/example/crud/EhCacheConfiguration.java
@@ -0,0 +1,26 @@
+package com.example.crud;
+
+import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.cache.ehcache.EhCacheCacheManager;
+
+@Configuration
+public class EhCacheConfiguration {
+
+ @Bean
+ public EhCacheCacheManager ehCacheCacheManager() {
+ return new EhCacheCacheManager(ehCacheManagerFactoryBean().getObject());
+ }
+
+
+ @Bean
+ public EhCacheManagerFactoryBean ehCacheManagerFactoryBean() {
+ EhCacheManagerFactoryBean cacheManagerFactoryBean = new EhCacheManagerFactoryBean();
+ cacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
+ cacheManagerFactoryBean.setShared(true);
+ return cacheManagerFactoryBean;
+ }
+
+}
diff --git a/src/main/java/com/example/crud/JGroups.java b/src/main/java/com/example/crud/JGroups.java
deleted file mode 100644
index a040a92..0000000
--- a/src/main/java/com/example/crud/JGroups.java
+++ /dev/null
@@ -1,236 +0,0 @@
-package com.example.crud;
-
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.util.*;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.locks.Lock;
-import java.util.regex.Pattern;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.jgroups.*;
-import org.jgroups.blocks.locking.LockService;
-
-public class JGroups {
- private Logger log = LoggerFactory.getLogger(getClass().getName());
- /* this variable indicates whether I have become the master or I'm just a client*/
- public volatile AtomicBoolean becomeMaster = new AtomicBoolean(false);
- /* The address of the server if we are a client or of ourself if we are
- * server */
- public String serverAddress;
- /* A channel on which to acquire a lock, so that only one can become server */
- private JChannel lockChannel;
- /* A shared channel ffor communication between client and master*/
- private JChannel communicationChannel;
- private LockService lockService;
- /* A thread which tries to acquire a lock */
- private Thread acquiringThread;
- /* A thread which listens for the server ip which may change */
- private Thread listeningThread;
- /* A thread which lists the status and initializes the acquiring thread*/
- private Thread statusThread;
- private String name;
- /* If we pass from being a client to being a server we must stop the listening
- * thread however we cannot call listeningThread.stop() but instead we change
- * the stopListening boolean to true */
- private boolean stopListening = false;
- /* This lock communicates I have finally become either master or client so
- * the serverAddress and becomeMaster variables are correctly set */
- public final Object finishedLock = new Object();
-
- public static void main(String[] args) throws Exception {
- //System.setProperty("jgroups.udp.mcast_addr", "127.0.0.1");
- Thread.currentThread().setName("MyMainThread");
- Random rand = new Random();
-
- JGroups master = new JGroups("Node" + rand.nextInt(10));
-
- master.lockChannel = new JChannel(JGroups.class.getClassLoader().getResource(
- "jgroups-l2-cache-udp-largecluster.xml"));
- master.lockChannel.connect("lock-channel");
-
- master.communicationChannel = new JChannel(
- JGroups.class.getClassLoader().getResource("jgroups-l2-cache-udp-largecluster.xml"));
- master.communicationChannel.connect("communication-channel");
-
- master.lockService = new LockService(master.lockChannel);
- master.startStatusPrinterThread();
- }
-
- public JGroups(String name) {
- this.name = name;
- }
-
- public JGroups() {
- try {
- Thread.currentThread().setName("MyMainThread");
- Random rand = new Random();
-
- this.name = ("Node" + rand.nextInt(10));
-
- lockChannel = new JChannel(JGroups.class.getClassLoader().getResource("/resource/udp.xml"));
- lockChannel.connect("lock-channel");
-
- communicationChannel = new JChannel(JGroups.class.getClassLoader().getResource("/resource/udp.xml"));
- communicationChannel.connect("communication-channel");
-
- lockService = new LockService(lockChannel);
- startStatusPrinterThread();
- }
- catch (Exception ex) {
- log.error(ex.getStackTrace().toString());
- }
- }
-
- public void startAcquiringThread() {
- acquiringThread = new Thread() {
- @Override
- public void run() {
- while (true) {
- //if you have become Master send your ip every now and then
- if (becomeMaster.get()) {
- try {
- StringBuffer buffer = new StringBuffer("serverip " + serverAddress);
- communicationChannel.send(new Message(null, buffer));
- }
- catch (Exception ex) {
- log.error(ex.getStackTrace().toString());
- }
- } else {
- try {
- Thread.currentThread().setName(name + "AcquiringThread");
- Lock lock = lockService.getLock("serverLock");
- if (lock.tryLock(4, TimeUnit.SECONDS)) {
- becomeMaster.set(true);
- stopListening = true;
- /* Now that I'm server I must find out my own ip address on which to listen */
- Enumeration networkInterfaces;
- try {
- networkInterfaces = NetworkInterface.getNetworkInterfaces();
- for (NetworkInterface netint : Collections.list(networkInterfaces)) {
- Enumeration inetAddresses = netint.getInetAddresses();
- for (InetAddress inetAddress : Collections.list(inetAddresses)) {
- if (isIPAddress(inetAddress.getHostAddress())
- && !inetAddress.getHostAddress().equals("127.0.0.1")) {
- serverAddress = inetAddress.getHostAddress();
- }
- }
- }
- /* I notify to the rest of the program I have correctly initialized
- * becomeMaster and serverAddress */
- synchronized (finishedLock) {
- finishedLock.notify();
- }
- }
- catch (Exception ex) {
- log.error(ex.getStackTrace().toString());
- System.exit(0);
- }
- log.info(Thread.currentThread().getName()
- + ": I acquired lock! will become master! my ip is " + serverAddress);
- } else {
- becomeMaster.set(false);
- stopListening = false;
- if (listeningThread == null || !listeningThread.isAlive()) {
- if (!stopListening) {
- //??? this codnition might be useless
- startListeningThread();
- }
- }
- }
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- }
- try {
- sleep(5000L);
- }
- catch (InterruptedException ex) {
- log.error(ex.getStackTrace().toString());
- }
- }
- }
- };
- acquiringThread.setDaemon(true);
- acquiringThread.start();
- }
-
- public void startListeningThread() {
- listeningThread = new Thread() {
- @Override
- public void run() {
- try {
- while (true) {
- Thread.currentThread().setName(name + "ListeningThread");
- communicationChannel.setReceiver(new ReceiverAdapter() {
- @Override
- public void receive(Message msg) {
- if (msg.getObject() != null) {
- String leaderServerAddress = (msg.getObject().toString().substring(9));
- if (isIPAddress(leaderServerAddress)) {
- serverAddress = leaderServerAddress;
- log.info(name + " Master server has ip" + serverAddress);
- /* I notify to the rest of the program I have correctly initialized
- * becomeMaster and serverAddress */
- synchronized (finishedLock) {
- finishedLock.notify();
- }
- } else {
- log.info(name + ": discarded message " + msg.getObject().toString());
- }
- }
- }
- });
- sleep(10000L);
- if (stopListening) {
- return;
- }
- }
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- }
- };
- listeningThread.setDaemon(true);
- listeningThread.start();
- }
-
- private void startStatusPrinterThread() {
- statusThread = new Thread() {
- @Override
- public void run() {
- Thread.currentThread().setName(name + "StatusPrinterThread");
- startAcquiringThread();
- while (true) {
- try {
- if (becomeMaster.get()) {
- log.info(name + " startStatusPrinterThread(): I am happily a Master!");
- } else {
- if (!acquiringThread.isAlive()) {
- startAcquiringThread();
- }
- }
- sleep(5000L);
- }
- catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- };
- statusThread.setDaemon(true);
- statusThread.start();
- }
-
- private static boolean isIPAddress(String str) {
- Pattern ipPattern = Pattern.compile("^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
- + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
- + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
- + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
- return ipPattern.matcher(str).matches();
- }
-}
diff --git a/src/main/java/com/example/crud/Main.java b/src/main/java/com/example/crud/Main.java
index 4641132..272e9a4 100644
--- a/src/main/java/com/example/crud/Main.java
+++ b/src/main/java/com/example/crud/Main.java
@@ -2,10 +2,11 @@ package com.example.crud;
import com.example.crud.entities.*;
import com.example.crud.repositories.InventoryRepository;
-import org.datanucleus.util.NucleusLogger;
-import org.infinispan.Cache;
-import org.infinispan.configuration.cache.ConfigurationBuilder;
-import org.infinispan.manager.DefaultCacheManager;
+import com.example.crud.repositories.PersonRepository;
+import org.datanucleus.api.jpa.JPAEntityManager;
+import org.datanucleus.state.ObjectProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
@@ -21,66 +22,101 @@ import java.util.Map;
*/
public class Main {
- public static void cacheTest() {
- // Construct a simple local cache manager with default configuration
- DefaultCacheManager cacheManager = new DefaultCacheManager();
- // Define local cache configuration
- cacheManager.defineConfiguration("local", new ConfigurationBuilder().build());
- // Obtain the local cache
- Cache cache = cacheManager.getCache("local");
- // Register a listener
- cache.addListener(new CacheClusterListener());
- // Store some values
- cache.put("key1", "value1");
- cache.put("key2", "value2");
- cache.put("key1", "newValue");
- // Stop the cache manager and release all resources
- cacheManager.stop();
- }
public static void main(String args[]) {
- //cacheTest();
+ Logger log = LoggerFactory.getLogger(Main.class);//getClass().getName());
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
- ctx.register(ApplicationConfig.class);
+ ctx.scan("com.example");
+ ctx.register(ApplicationConfiguration.class);
ctx.refresh();
+ // Enable MongoDB logging in general
+ System.setProperty("DEBUG.MONGO", "true");
+
+ // Enable DB operation tracing
+ System.setProperty("DB.TRACE", "true");
+
// Create an EntityManagerFactory for this "persistence-unit"
// See the file "META-INF/persistence.xml"
- EntityManagerFactory emf = Persistence.createEntityManagerFactory("crud");
- EntityManagerFactory emf_mongo = Persistence.createEntityManagerFactory("mongo");
- //MergingPersistenceUnitmanager
+ EntityManagerFactory cassandraEntityManagerFactory = Persistence.createEntityManagerFactory("crud");
+ EntityManagerFactory mongoEntityManagerFactory = Persistence.createEntityManagerFactory("mongo");
// TODO:
- // * types: int, bool, etc.
- // * Set<>
- // * L2/Caching via Infinispan (embedded, clustered)
- // * MergingPersistenceUnitmanager
- // * Draft/(Fluent)Builder Immutable Entites
+ // * LOCAL_QUORUM
+ // * compound primary keys
+ // * pillar for DDL
+ // * metrics
+ // * com.datastax.driver.core.Cluster.builder().withQueryOptions(new QueryOptions().setConsistencyLevel(ConsistencyLevel.QUORUM))
+ // * https://github.com/brndnmtthws/metrics-cassandra (c* as a sink for metrics)
+ // * https://github.com/addthis/metrics-reporter-config
+
+ EntityManager em;
+ EntityTransaction tx;
+ JpaRepositoryFactory factory;
+
+ //org.datanucleus.api.jpa.JPAEntityTransaction tx = (org.datanucleus.api.jpa.JPAEntityTransaction)pm.currentTransaction();
+ //tx.setOption("transaction.isolation", 2);
+
+ // Add a person to MongoDB
+ em = mongoEntityManagerFactory.createEntityManager();
+ Person person;
+ /*
+ factory = new JpaRepositoryFactory(em);
+ PersonRepository repository = factory.getRepository(PersonRepository.class);
+ person = new Person();
+ person.setPersonFirstName("James");
+ person.setPersonLastName("Bond");
+ person.setAge(42);
+ repository.save(person);
+ */
+ tx = em.getTransaction();
+ try {
+ tx.begin();
+ person = new Person();
+ person.setPersonFirstName("James");
+ person.setPersonLastName("Bond");
+ person.setAge(42);
+ em.merge(person);
+
+ List objs = ((JPAEntityManager) em).getExecutionContext().getObjectsToBeFlushed();
+ for (Object o : objs) {
+ log.debug("to be flushed: " + o.toString());
+ }
+ tx.commit();
+ } finally {
+ if (tx.isActive()) {
+ tx.rollback();
+ }
+ em.close(); // This will detach all current managed objects
+ }
// Persistence of a Product and a Book.
- EntityManager em = emf.createEntityManager();
- EntityTransaction tx = em.getTransaction();
+ em = cassandraEntityManagerFactory.createEntityManager();
+ tx = em.getTransaction();
try {
tx.begin();
Inventory inv = em.merge(new Inventory("My Inventory"));
+ inv.setDescription("This is my initial description.");
Product product = new Product("Sony Discman", "A standard discman from Sony", 200.00);
inv.addProduct(product);
Book book = new Book("Lord of the Rings by Tolkien", "The classic story", 49.99, "JRR Tolkien",
"12345678", "MyBooks Factory");
- Magazine magazine = new Magazine("Field and Stream", "A hunter's guide to the outdoors.", 3.29, "F&S, Inc.", "23984729347", "F&S, Inc.");
+ Magazine magazine = new Magazine("Field and Stream", "A hunter's guide to the outdoors.", 3.29, "F&S, Inc.",
+ "23984729347", "F&S, Inc.");
+
+ //product.setSeller(person);
+ //book.setSeller(person);
+ //magazine.setSeller(person);
inv.addProduct(book);
inv.addProduct(magazine);
em.persist(inv);
tx.commit();
-// SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(inv);
-// SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(product);
-// System.out.println("Product and Book have been persisted, inventory: " + inv.getPrimaryKey().toString() + ", product: " + product.getPrimaryKey().toString());
}
catch (Exception e) {
- NucleusLogger.GENERAL.error(">> Exception persisting data", e);
+ log.error(">> Exception persisting data", e);
System.err.println("Error persisting data : " + e.getMessage());
return;
} finally {
@@ -89,11 +125,11 @@ public class Main {
}
em.close();
}
- emf.getCache().evictAll();
+ cassandraEntityManagerFactory.getCache().evictAll();
System.out.println("");
// Perform a retrieve of the Inventory and detach it (by closing the EM)
- em = emf.createEntityManager();
+ em = cassandraEntityManagerFactory.createEntityManager();
tx = em.getTransaction();
Inventory inv = null;
try {
@@ -114,7 +150,7 @@ public class Main {
tx.commit();
}
catch (Exception e) {
- NucleusLogger.GENERAL.error(">> Exception performing find() on data", e);
+ log.error(">> Exception performing find() on data", e);
System.err.println("Error performing find() on data : " + e.getMessage());
return;
} finally {
@@ -128,17 +164,14 @@ public class Main {
}
System.out.println("");
- // Add a person to MongoDB
- em = emf_mongo.createEntityManager();
+ // Update a person to MongoDB
+ em = mongoEntityManagerFactory.createEntityManager();
tx = em.getTransaction();
- Person person;
try {
tx.begin();
- person = new Person();
- person.setPersonFirstName("James");
- person.setPersonLastName("Bond");
- person.setAge(42);
- em.merge(person);
+ person = em.find(Person.class, person.getPersonId());
+ person.setPersonLastName("Blunder");
+ person.setAge(43);
tx.commit();
} finally {
if (tx.isActive()) {
@@ -148,7 +181,7 @@ public class Main {
}
// Perform some query operations
- em = emf.createEntityManager();
+ em = cassandraEntityManagerFactory.createEntityManager();
tx = em.getTransaction();
try {
tx.begin();
@@ -173,7 +206,7 @@ public class Main {
tx.commit();
}
catch (Exception e) {
- NucleusLogger.GENERAL.error(">> Exception querying data", e);
+ log.error(">> Exception querying data", e);
System.err.println("Error querying data : " + e.getMessage());
return;
} finally {
@@ -184,16 +217,54 @@ public class Main {
}
System.out.println("");
- em = emf.createEntityManager();
- JpaRepositoryFactory factory = new JpaRepositoryFactory(em);
- InventoryRepository repository = factory.getRepository(InventoryRepository.class);
- Inventory inventory = repository.findByName("My Inventory");
- System.out.println("SpringData/JPA: " + inventory.toString());
- em.close();
+ em = cassandraEntityManagerFactory.createEntityManager();
+ factory = new JpaRepositoryFactory(em);
+ tx = em.getTransaction();
+ try {
+ tx.begin();
+ InventoryRepository repository = factory.getRepository(InventoryRepository.class);
+ Inventory inventory = repository.findByName("My Inventory");
+ System.out.println("SpringData/JPA: " + inventory.toString());
+ inventory.setDescription("This is my updated description.");
+ tx.rollback();
+ }
+ catch (Exception e) {
+ log.error(">> Exception in bulk delete of data", e);
+ System.err.println("Error in bulk delete of data : " + e.getMessage());
+ return;
+ } finally {
+ if (tx.isActive()) {
+ tx.rollback();
+ }
+ em.close();
+ }
+
+ em = cassandraEntityManagerFactory.createEntityManager();
+ factory = new JpaRepositoryFactory(em);
+ tx = em.getTransaction();
+ try {
+ tx.begin();
+ InventoryRepository repository = factory.getRepository(InventoryRepository.class);
+ Inventory inventory = repository.findByName("My Inventory");
+ inventory.setDescription("This is the final description.");
+ repository.save(inventory);
+ tx.commit();
+ }
+ catch (Exception e) {
+ log.error(">> Exception in bulk delete of data", e);
+ System.err.println("Error in bulk delete of data : " + e.getMessage());
+ return;
+ } finally {
+ if (tx.isActive()) {
+ tx.rollback();
+ }
+ em.close();
+ }
+
// Clean out the database
- emf.getCache().evictAll();
- em = emf.createEntityManager();
+ cassandraEntityManagerFactory.getCache().evictAll();
+ em = cassandraEntityManagerFactory.createEntityManager();
tx = em.getTransaction();
try {
tx.begin();
@@ -221,7 +292,7 @@ public class Main {
tx.commit();
}
catch (Exception e) {
- NucleusLogger.GENERAL.error(">> Exception in bulk delete of data", e);
+ log.error(">> Exception in bulk delete of data", e);
System.err.println("Error in bulk delete of data : " + e.getMessage());
return;
} finally {
@@ -233,6 +304,6 @@ public class Main {
System.out.println("");
System.out.println("End of Tutorial");
- emf.close();
+ cassandraEntityManagerFactory.close();
}
}
diff --git a/src/main/java/com/example/crud/entities/AbstractEntity.java b/src/main/java/com/example/crud/entities/AbstractEntity.java
index 8fd9a1a..597638e 100644
--- a/src/main/java/com/example/crud/entities/AbstractEntity.java
+++ b/src/main/java/com/example/crud/entities/AbstractEntity.java
@@ -10,17 +10,23 @@ import java.io.Serializable;
@MappedSuperclass
public abstract class AbstractEntity {
+ @Version
+ protected long version;
+
+ /*
+ // SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(inv);
+ // SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(product);
+ //System.out.println("Product and Book have been persisted, inventory: " + inv.getPrimaryKey().toString() + ", product: " + product.getPrimaryKey().toString());
+
@Transient
@Autowired
EntityManagerFactory emf;
- @Version
- protected long version;
-
public ID getPrimaryKey() {
final PersistenceUnitUtil util = emf.getPersistenceUnitUtil();
Object id = util.getIdentifier(this);
return (ID)id;
}
+ */
}
diff --git a/src/main/java/com/example/crud/entities/Book.java b/src/main/java/com/example/crud/entities/Book.java
index 5f824e6..affb696 100644
--- a/src/main/java/com/example/crud/entities/Book.java
+++ b/src/main/java/com/example/crud/entities/Book.java
@@ -29,6 +29,9 @@ public class Book extends Product
@Basic
private String publisher = null;
+ @Basic
+ private boolean paperback = false;
+
/**
* Default Constructor.
**/
diff --git a/src/main/java/com/example/crud/entities/Inventory.java b/src/main/java/com/example/crud/entities/Inventory.java
index 8324f98..379b63d 100644
--- a/src/main/java/com/example/crud/entities/Inventory.java
+++ b/src/main/java/com/example/crud/entities/Inventory.java
@@ -20,6 +20,9 @@ public class Inventory extends AbstractAuditableEntity {
@Id
private String name=null;
+ @Basic
+ private String description;
+
@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH }, fetch = FetchType.EAGER)
private Set products = new HashSet();
@@ -42,4 +45,7 @@ public class Inventory extends AbstractAuditableEntity {
products.clear();
}
+ public void setDescription(String description) {
+ this.description = description;
+ }
}
diff --git a/src/main/java/com/example/crud/entities/Person.java b/src/main/java/com/example/crud/entities/Person.java
index 37342f6..8655989 100644
--- a/src/main/java/com/example/crud/entities/Person.java
+++ b/src/main/java/com/example/crud/entities/Person.java
@@ -51,6 +51,13 @@ public class Person extends AbstractAuditableEntity {
@OneToMany(mappedBy = "seller")
private List products;
+ public Person() {
+ }
+
+ public Person(String personId) {
+ this.personId = personId;
+ }
+
/**
* Gets the person id.
*
diff --git a/src/main/java/com/example/crud/metrics/CoalescingReporter.java b/src/main/java/com/example/crud/metrics/CoalescingReporter.java
new file mode 100644
index 0000000..dfbdc7a
--- /dev/null
+++ b/src/main/java/com/example/crud/metrics/CoalescingReporter.java
@@ -0,0 +1,229 @@
+package com.example.crud.metrics;
+
+import com.codahale.metrics.Counter;
+import com.codahale.metrics.Gauge;
+import com.codahale.metrics.Histogram;
+import com.codahale.metrics.Meter;
+import com.codahale.metrics.MetricFilter;
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.ScheduledReporter;
+import com.codahale.metrics.Snapshot;
+import com.codahale.metrics.Timer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Marker;
+
+import java.util.Map.Entry;
+import java.util.SortedMap;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A reporter class for logging metrics values to a {@link Logger} periodically, similar to
+ * {@link com.codahale.metrics.ConsoleReporter} or {@link com.codahale.metrics.CsvReporter}, but using
+ * the logging framework instead. It also supports specifying a {@link Marker} instance that can be used
+ * by custom appenders and filters for the bound logging toolkit to further process metrics reports.
+ */
+public final class CoalescingReporter extends ScheduledReporter {
+
+ private final Logger logger;
+ private final Marker marker;
+
+ /**
+ * Returns a new {@link Builder} for {@link CoalescingReporter}.
+ *
+ * @param registry the registry to report
+ * @return a {@link Builder} instance for a {@link CoalescingReporter}
+ */
+ public static Builder forRegistry(MetricRegistry registry) {
+ return new Builder(registry);
+ }
+
+ private CoalescingReporter(MetricRegistry registry,
+ Logger logger,
+ Marker marker,
+ TimeUnit rateUnit,
+ TimeUnit durationUnit,
+ MetricFilter filter) {
+ super(registry, "logger-reporter", filter, rateUnit, durationUnit);
+ this.logger = logger;
+ this.marker = marker;
+ }
+
+ @Override
+ public void report(SortedMap gauges,
+ SortedMap counters,
+ SortedMap histograms,
+ SortedMap meters,
+ SortedMap timers) {
+ StringBuilder data = new StringBuilder();
+ for (Entry entry : gauges.entrySet()) {
+ addGauge(data, entry.getKey(), entry.getValue());
+ }
+
+ for (Entry entry : counters.entrySet()) {
+ addCounter(data, entry.getKey(), entry.getValue());
+ }
+
+ for (Entry entry : histograms.entrySet()) {
+ addHistogram(data, entry.getKey(), entry.getValue());
+ }
+
+ for (Entry entry : meters.entrySet()) {
+ addMeter(data, entry.getKey(), entry.getValue());
+ }
+
+ for (Entry entry : timers.entrySet()) {
+ addTimer(data, entry.getKey(), entry.getValue());
+ }
+ logger.info(marker, data.toString());
+ }
+
+ private void addTimer(StringBuilder data, String name, Timer timer) {
+ final Snapshot snapshot = timer.getSnapshot();
+ data.append(" type=timer.").append(name).append(":");
+ data.append(" count=").append(timer.getCount());
+ data.append(", min=").append(convertDuration(snapshot.getMin()));
+ data.append(", max=").append(convertDuration(snapshot.getMax()));
+ data.append(", mean=").append(convertDuration(snapshot.getMean()));
+ data.append(", stdDev=").append(convertDuration(snapshot.getStdDev()));
+ data.append(", median=").append(convertDuration(snapshot.getMedian()));
+ data.append(", p75=").append(convertDuration(snapshot.get75thPercentile()));
+ data.append(", p95=").append(convertDuration(snapshot.get95thPercentile()));
+ data.append(", p98=").append(convertDuration(snapshot.get98thPercentile()));
+ data.append(", p99=").append(convertDuration(snapshot.get99thPercentile()));
+ data.append(", 999=").append(convertDuration(snapshot.get999thPercentile()));
+ data.append(", mean_rate=").append(convertRate(timer.getMeanRate()));
+ data.append(", m1=").append(convertRate(timer.getMeanRate()));
+ data.append(", m5=").append(convertRate(timer.getMeanRate()));
+ data.append(", m15=").append(convertRate(timer.getMeanRate()));
+ data.append(", rate_unit=").append(getRateUnit());
+ data.append(", duration_unit=").append(getDurationUnit());
+ }
+
+ private void addMeter(StringBuilder data, String name, Meter meter) {
+ data.append(" type=meter.").append(name).append(":");
+ data.append(" count=").append(meter.getCount());
+ data.append(", mean_rate=").append(convertRate(meter.getMeanRate()));
+ data.append(", m1=").append(convertRate(meter.getOneMinuteRate()));
+ data.append(", m5=").append(convertRate(meter.getFiveMinuteRate()));
+ data.append(", m15=").append(convertRate(meter.getFifteenMinuteRate()));
+ data.append(", rate_unit=").append(getRateUnit());
+ }
+
+ private void addHistogram(StringBuilder data, String name, Histogram histogram) {
+ final Snapshot snapshot = histogram.getSnapshot();
+ data.append(" type=histogram.").append(name).append(":");
+ data.append(" count=").append(histogram.getCount());
+ data.append(", min=").append(snapshot.getMin());
+ data.append(", max=").append(snapshot.getMax());
+ data.append(", mean=").append(snapshot.getMean());
+ data.append(", stdDev=").append(snapshot.getStdDev());
+ data.append(", median=").append(snapshot.getMedian());
+ data.append(", p75=").append(snapshot.get75thPercentile());
+ data.append(", p95=").append(snapshot.get95thPercentile());
+ data.append(", p98=").append(snapshot.get98thPercentile());
+ data.append(", p99=").append(snapshot.get99thPercentile());
+ data.append(", 999=").append(snapshot.get999thPercentile());
+ }
+
+ private void addCounter(StringBuilder data, String name, Counter counter) {
+ data.append(" counter.").append(name).append(": ").append(counter.getCount());
+ }
+
+ private void addGauge(StringBuilder data, String name, Gauge gauge) {
+ data.append(" gauge.").append(name).append(": ").append(gauge.getValue());
+ }
+
+ @Override
+ protected String getRateUnit() {
+ return "events/" + super.getRateUnit();
+ }
+
+ /**
+ * A builder for {@link com.codahale.metrics.CsvReporter} instances. Defaults to logging to {@code metrics}, not
+ * using a marker, converting rates to events/second, converting durations to milliseconds, and
+ * not filtering metrics.
+ */
+ public static final class Builder {
+ private final MetricRegistry registry;
+ private Logger logger;
+ private Marker marker;
+ private TimeUnit rateUnit;
+ private TimeUnit durationUnit;
+ private MetricFilter filter;
+
+ private Builder(MetricRegistry registry) {
+ this.registry = registry;
+ this.logger = LoggerFactory.getLogger("metrics");
+ this.marker = null;
+ this.rateUnit = TimeUnit.SECONDS;
+ this.durationUnit = TimeUnit.MILLISECONDS;
+ this.filter = MetricFilter.ALL;
+ }
+
+ /**
+ * Log metrics to the given logger.
+ *
+ * @param logger a {@link Logger}
+ * @return {@code this}
+ */
+ public Builder outputTo(Logger logger) {
+ this.logger = logger;
+ return this;
+ }
+
+ /**
+ * Mark all logged metrics with the given marker.
+ *
+ * @param marker a {@link Marker}
+ * @return {@code this}
+ */
+ public Builder markWith(Marker marker) {
+ this.marker = marker;
+ return this;
+ }
+
+ /**
+ * Convert rates to the given time unit.
+ *
+ * @param rateUnit a unit of time
+ * @return {@code this}
+ */
+ public Builder convertRatesTo(TimeUnit rateUnit) {
+ this.rateUnit = rateUnit;
+ return this;
+ }
+
+ /**
+ * Convert durations to the given time unit.
+ *
+ * @param durationUnit a unit of time
+ * @return {@code this}
+ */
+ public Builder convertDurationsTo(TimeUnit durationUnit) {
+ this.durationUnit = durationUnit;
+ return this;
+ }
+
+ /**
+ * Only report metrics which match the given filter.
+ *
+ * @param filter a {@link MetricFilter}
+ * @return {@code this}
+ */
+ public Builder filter(MetricFilter filter) {
+ this.filter = filter;
+ return this;
+ }
+
+ /**
+ * Builds a {@link CoalescingReporter} with the given properties.
+ *
+ * @return a {@link CoalescingReporter}
+ */
+ public CoalescingReporter build() {
+ return new CoalescingReporter(registry, logger, marker, rateUnit, durationUnit, filter);
+ }
+ }
+
+}
diff --git a/src/main/java/com/example/crud/metrics/CoalescingReporterElementParser.java b/src/main/java/com/example/crud/metrics/CoalescingReporterElementParser.java
new file mode 100644
index 0000000..fdf136d
--- /dev/null
+++ b/src/main/java/com/example/crud/metrics/CoalescingReporterElementParser.java
@@ -0,0 +1,38 @@
+package com.example.crud.metrics;
+
+import com.ryantenney.metrics.spring.reporter.AbstractReporterElementParser;
+
+/**
+ * Reporter for metrics-spring which logs more compact, all in one line instead of one line for each metric.
+ */
+public class CoalescingReporterElementParser extends AbstractReporterElementParser {
+
+ private static final String FILTER_REF = "filter-ref";
+ private static final String FILTER_PATTERN = "filter";
+
+ @Override
+ public String getType() {
+ return "compact-slf4j";
+ }
+
+ @Override
+ protected Class> getBeanClass() {
+ return CoalescingReporterFactoryBean.class;
+ }
+
+ @Override
+ protected void validate(ValidationContext c) {
+ c.require(CoalescingReporterFactoryBean.PERIOD, DURATION_STRING_REGEX, "Period is required and must be in the form '\\d+(ns|us|ms|s|m|h|d)'");
+ c.optional(CoalescingReporterFactoryBean.MARKER);
+ c.optional(CoalescingReporterFactoryBean.LOGGER);
+ c.optional(CoalescingReporterFactoryBean.RATE_UNIT, TIMEUNIT_STRING_REGEX, "Rate unit must be one of the enum constants from java.util.concurrent.TimeUnit");
+ c.optional(CoalescingReporterFactoryBean.DURATION_UNIT, TIMEUNIT_STRING_REGEX, "Duration unit must be one of the enum constants from java.util.concurrent.TimeUnit");
+ c.optional(FILTER_PATTERN);
+ c.optional(FILTER_REF);
+ if (c.has(FILTER_PATTERN) && c.has(FILTER_REF)) {
+ c.reject(FILTER_REF, "Reporter element must not specify both the 'filter' and 'filter-ref' attributes");
+ }
+ c.rejectUnmatchedProperties();
+ }
+
+}
diff --git a/src/main/java/com/example/crud/metrics/CoalescingReporterFactoryBean.java b/src/main/java/com/example/crud/metrics/CoalescingReporterFactoryBean.java
new file mode 100644
index 0000000..7d31e1a
--- /dev/null
+++ b/src/main/java/com/example/crud/metrics/CoalescingReporterFactoryBean.java
@@ -0,0 +1,54 @@
+package com.example.crud.metrics;
+
+import com.ryantenney.metrics.spring.reporter.AbstractScheduledReporterFactoryBean;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MarkerFactory;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * CoalescingReporterFactoryBean.
+ */
+public class CoalescingReporterFactoryBean extends AbstractScheduledReporterFactoryBean {
+
+ /** Period attribute. */
+ public static final String PERIOD = "period";
+ /** Duration unit. */
+ public static final String DURATION_UNIT = "duration-unit";
+ /** Rate unit. */
+ public static final String RATE_UNIT = "rate-unit";
+ /** Marker. */
+ public static final String MARKER = "marker";
+ /** Logger. */
+ public static final String LOGGER = "logger";
+
+ @Override
+ public Class getObjectType() {
+ return CoalescingReporter.class;
+ }
+
+ @Override
+ protected CoalescingReporter createInstance() {
+ final CoalescingReporter.Builder reporter = CoalescingReporter.forRegistry(getMetricRegistry());
+ if (hasProperty(DURATION_UNIT)) {
+ reporter.convertDurationsTo(getProperty(DURATION_UNIT, TimeUnit.class));
+ }
+ if (hasProperty(RATE_UNIT)) {
+ reporter.convertRatesTo(getProperty(RATE_UNIT, TimeUnit.class));
+ }
+ reporter.filter(getMetricFilter());
+ if (hasProperty(MARKER)) {
+ reporter.markWith(MarkerFactory.getMarker(getProperty(MARKER)));
+ }
+ if (hasProperty(LOGGER)) {
+ reporter.outputTo(LoggerFactory.getLogger(getProperty(LOGGER)));
+ }
+ return reporter.build();
+ }
+
+ @Override
+ protected long getPeriod() {
+ return convertDurationString(getProperty(PERIOD));
+ }
+
+}
diff --git a/src/main/java/com/example/crud/metrics/MetricsConfiguration.java b/src/main/java/com/example/crud/metrics/MetricsConfiguration.java
new file mode 100644
index 0000000..c73e013
--- /dev/null
+++ b/src/main/java/com/example/crud/metrics/MetricsConfiguration.java
@@ -0,0 +1,151 @@
+package com.example.crud.metrics;
+
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.util.ContextInitializer;
+import ch.qos.logback.core.joran.spi.JoranException;
+import com.codahale.metrics.*;
+import com.codahale.metrics.health.HealthCheckRegistry;
+import com.codahale.metrics.jvm.*;
+import com.codahale.metrics.logback.InstrumentedAppender;
+import com.datastax.driver.core.Cluster;
+import com.datastax.driver.core.Session;
+import com.ryantenney.metrics.spring.config.annotation.EnableMetrics;
+import com.ryantenney.metrics.spring.config.annotation.MetricsConfigurerAdapter;
+import org.datanucleus.store.StoreManager;
+import org.datanucleus.store.connection.ManagedConnection;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.PostConstruct;
+import javax.persistence.EntityManagerFactory;
+import java.lang.management.ManagementFactory;
+import java.util.concurrent.TimeUnit;
+
+@Configuration
+@EnableMetrics(proxyTargetClass = true)
+public class MetricsConfiguration extends MetricsConfigurerAdapter {
+
+ private static final String PROP_METRIC_REG_JVM_MEMORY = "jvm.memory";
+ private static final String PROP_METRIC_REG_JVM_GARBAGE = "jvm.garbage";
+ private static final String PROP_METRIC_REG_JVM_THREADS = "jvm.threads";
+ private static final String PROP_METRIC_REG_JVM_FILES = "jvm.files";
+ private static final String PROP_METRIC_REG_JVM_BUFFERS = "jvm.buffers";
+
+ private final Logger log = (Logger)LoggerFactory.getLogger(getClass().getName());
+
+ private MetricRegistry metricRegistry = new MetricRegistry();
+
+ private HealthCheckRegistry healthCheckRegistry = new HealthCheckRegistry();
+
+ @Autowired
+ ApplicationContext context;
+
+ @Override
+ @Bean
+ public MetricRegistry getMetricRegistry() {
+ return metricRegistry;
+ }
+
+ @Override
+ @Bean
+ public HealthCheckRegistry getHealthCheckRegistry() {
+ return healthCheckRegistry;
+ }
+
+ @PostConstruct
+ public void init() {
+/*
+ final LoggerContext factory = (LoggerContext) LoggerFactory.getILoggerFactory();
+ final Logger root = factory.getLogger("console");//Logger.ROOT_LOGGER_NAME);
+
+ final InstrumentedAppender metrics = new InstrumentedAppender();
+ metrics.setContext(root.getLoggerContext());
+ metrics.start();
+ root.addAppender(metrics);
+*/
+
+ LoggerContext loggerContext = (LoggerContext)LoggerFactory.getILoggerFactory();
+ loggerContext.reset();
+ ContextInitializer initializer = new ContextInitializer(loggerContext);
+ try {
+ initializer.autoConfig();
+ } catch (JoranException e) {
+ e.printStackTrace();
+ }
+
+
+ log.debug("Registering JVM gauges");
+ metricRegistry.registerAll(new OperatingSystemGaugeSet());
+ metricRegistry.register(PROP_METRIC_REG_JVM_MEMORY, new MemoryUsageGaugeSet());
+ metricRegistry.register(PROP_METRIC_REG_JVM_GARBAGE, new GarbageCollectorMetricSet());
+ metricRegistry.register(PROP_METRIC_REG_JVM_THREADS, new ThreadStatesGaugeSet());
+ metricRegistry.register(PROP_METRIC_REG_JVM_FILES, new FileDescriptorRatioGauge());
+ metricRegistry.register(PROP_METRIC_REG_JVM_BUFFERS,
+ new BufferPoolMetricSet(ManagementFactory.getPlatformMBeanServer()));
+
+ Cluster cluster = context.getBean(Cluster.class);
+ cluster.getMetrics().getRegistry().addListener(
+ new com.codahale.metrics.MetricRegistryListener() {
+
+ private final String METRIC_NAME_PREFIX = "com.datastax.";
+
+ @Override
+ public void onGaugeAdded(String name, Gauge> gauge) {
+ //if (metricRegistry.getNames().contains(name)) {
+ // name is already taken, maybe prefix with a namespace
+ //} else {
+ metricRegistry.register(METRIC_NAME_PREFIX + name, gauge);
+ }
+
+ @Override
+ public void onGaugeRemoved(String name) {
+ }
+
+ @Override
+ public void onCounterAdded(String name, Counter counter) {
+ metricRegistry.register(METRIC_NAME_PREFIX + name, counter);
+ }
+
+ @Override
+ public void onCounterRemoved(String name) {
+ }
+
+ @Override
+ public void onHistogramAdded(String name, Histogram histogram) {
+ metricRegistry.register(METRIC_NAME_PREFIX + name, histogram);
+ }
+
+ @Override
+ public void onHistogramRemoved(String name) {
+ }
+
+ @Override
+ public void onMeterAdded(String name, Meter meter) {
+ metricRegistry.register(METRIC_NAME_PREFIX + name, meter);
+ }
+
+ @Override
+ public void onMeterRemoved(String name) {
+ }
+
+ @Override
+ public void onTimerAdded(String name, Timer timer) {
+ metricRegistry.register(METRIC_NAME_PREFIX + name, timer);
+ }
+
+ @Override
+ public void onTimerRemoved(String name) {
+ }
+ });
+ CoalescingReporter reporter = CoalescingReporter.forRegistry(metricRegistry)
+ .convertRatesTo(TimeUnit.SECONDS)
+ .convertDurationsTo(TimeUnit.MILLISECONDS)
+ .build();
+ reporter.start(5, TimeUnit.SECONDS);
+ }
+
+}
diff --git a/src/main/java/com/example/crud/metrics/OperatingSystemGaugeSet.java b/src/main/java/com/example/crud/metrics/OperatingSystemGaugeSet.java
new file mode 100644
index 0000000..8149876
--- /dev/null
+++ b/src/main/java/com/example/crud/metrics/OperatingSystemGaugeSet.java
@@ -0,0 +1,125 @@
+package com.example.crud.metrics;
+
+import com.codahale.metrics.Gauge;
+import com.codahale.metrics.Metric;
+import com.codahale.metrics.MetricSet;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.OperatingSystemMXBean;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * A set of gauges for operating system settings.
+ */
+public class OperatingSystemGaugeSet implements MetricSet {
+
+ private final OperatingSystemMXBean mxBean;
+ private final Optional committedVirtualMemorySize;
+ private final Optional totalSwapSpaceSize;
+ private final Optional freeSwapSpaceSize;
+ private final Optional processCpuTime;
+ private final Optional freePhysicalMemorySize;
+ private final Optional totalPhysicalMemorySize;
+ private final Optional openFileDescriptorCount;
+ private final Optional maxFileDescriptorCount;
+ private final Optional systemCpuLoad;
+ private final Optional processCpuLoad;
+
+ /**
+ * Creates new gauges using the platform OS bean.
+ */
+ public OperatingSystemGaugeSet() {
+ this(ManagementFactory.getOperatingSystemMXBean());
+ }
+
+ /**
+ * Creates a new gauges using the given OS bean.
+ *
+ * @param mxBean an {@link OperatingSystemMXBean}
+ */
+ public OperatingSystemGaugeSet(OperatingSystemMXBean mxBean) {
+ this.mxBean = mxBean;
+
+ committedVirtualMemorySize = getMethod("getCommittedVirtualMemorySize");
+ totalSwapSpaceSize = getMethod("getTotalSwapSpaceSize");
+ freeSwapSpaceSize = getMethod("getFreeSwapSpaceSize");
+ processCpuTime = getMethod("getProcessCpuTime");
+ freePhysicalMemorySize = getMethod("getFreePhysicalMemorySize");
+ totalPhysicalMemorySize = getMethod("getTotalPhysicalMemorySize");
+ openFileDescriptorCount = getMethod("getOpenFileDescriptorCount");
+ maxFileDescriptorCount = getMethod("getMaxFileDescriptorCount");
+ systemCpuLoad = getMethod("getSystemCpuLoad");
+ processCpuLoad = getMethod("getProcessCpuLoad");
+ }
+
+
+ @Override
+ public Map getMetrics() {
+ final Map gauges = new HashMap<>();
+
+ gauges.put("committedVirtualMemorySize", (Gauge) () -> invokeLong(committedVirtualMemorySize));
+ gauges.put("totalSwapSpaceSize", (Gauge) () -> invokeLong(totalSwapSpaceSize));
+ gauges.put("freeSwapSpaceSize", (Gauge) () -> invokeLong(freeSwapSpaceSize));
+ gauges.put("processCpuTime", (Gauge) () -> invokeLong(processCpuTime));
+ gauges.put("freePhysicalMemorySize", (Gauge) () -> invokeLong(freePhysicalMemorySize));
+ gauges.put("totalPhysicalMemorySize", (Gauge) () -> invokeLong(totalPhysicalMemorySize));
+ gauges.put("fd.usage", (Gauge) () -> invokeRatio(openFileDescriptorCount, maxFileDescriptorCount));
+ gauges.put("systemCpuLoad", (Gauge) () -> invokeDouble(systemCpuLoad));
+ gauges.put("processCpuLoad", (Gauge) () -> invokeDouble(processCpuLoad));
+
+ return gauges;
+ }
+
+ private Optional getMethod(String name) {
+ try {
+ final Method method = mxBean.getClass().getDeclaredMethod(name);
+ method.setAccessible(true);
+ return Optional.of(method);
+ } catch (NoSuchMethodException e) {
+ return Optional.empty();
+ }
+ }
+
+ private long invokeLong(Optional method) {
+ if (method.isPresent()) {
+ try {
+ return (long) method.get().invoke(mxBean);
+ } catch (IllegalAccessException | InvocationTargetException ite) {
+ return 0L;
+ }
+ }
+ return 0L;
+ }
+
+ private double invokeDouble(Optional method) {
+ if (method.isPresent()) {
+ try {
+ return (double) method.get().invoke(mxBean);
+ } catch (IllegalAccessException | InvocationTargetException ite) {
+ return 0.0;
+ }
+ }
+ return 0.0;
+ }
+
+ private double invokeRatio(Optional numeratorMethod, Optional denominatorMethod) {
+ if (numeratorMethod.isPresent() && denominatorMethod.isPresent()) {
+ try {
+ long numerator = (long) numeratorMethod.get().invoke(mxBean);
+ long denominator = (long) denominatorMethod.get().invoke(mxBean);
+ if (0 == denominator) {
+ return Double.NaN;
+ }
+ return 1.0 * numerator / denominator;
+ } catch (IllegalAccessException | InvocationTargetException ite) {
+ return Double.NaN;
+ }
+ }
+ return Double.NaN;
+ }
+
+}
diff --git a/src/main/java/com/example/crud/metrics/SpringConfiguringClass.java b/src/main/java/com/example/crud/metrics/SpringConfiguringClass.java
new file mode 100644
index 0000000..ff84ff4
--- /dev/null
+++ b/src/main/java/com/example/crud/metrics/SpringConfiguringClass.java
@@ -0,0 +1,22 @@
+package com.example.crud.metrics;
+
+import java.util.concurrent.TimeUnit;
+import org.springframework.context.annotation.Configuration;
+import com.codahale.metrics.ConsoleReporter;
+import com.codahale.metrics.MetricRegistry;
+import com.ryantenney.metrics.spring.config.annotation.EnableMetrics;
+import com.ryantenney.metrics.spring.config.annotation.MetricsConfigurerAdapter;
+
+@Configuration
+@EnableMetrics
+public class SpringConfiguringClass extends MetricsConfigurerAdapter {
+
+ @Override
+ public void configureReporters(MetricRegistry metricRegistry) {
+ // registerReporter allows the MetricsConfigurerAdapter to
+ // shut down the reporter when the Spring context is closed
+ registerReporter(ConsoleReporter.forRegistry(metricRegistry).build())
+ .start(1, TimeUnit.MINUTES);
+ }
+
+}
diff --git a/src/main/java/com/example/crud/repositories/InventoryRepository.java b/src/main/java/com/example/crud/repositories/InventoryRepository.java
index ecaa720..9f429a4 100644
--- a/src/main/java/com/example/crud/repositories/InventoryRepository.java
+++ b/src/main/java/com/example/crud/repositories/InventoryRepository.java
@@ -1,8 +1,6 @@
package com.example.crud.repositories;
-import com.codahale.metrics.annotation.Metered;
import com.example.crud.entities.Inventory;
-import io.astefanutti.metrics.aspectj.Metrics;
import org.datanucleus.api.jpa.annotations.ReadOnly;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
@@ -12,6 +10,7 @@ import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;
+import java.beans.Transient;
import java.util.List;
//@Metrics(registry = "${this.registry}")
@@ -31,4 +30,7 @@ public interface InventoryRepository extends JpaRepository, J
@CacheEvict(value = "inventory", key = "#name")
void deleteInventoryBy(String name);
+ @Transactional
+ //CacheEvict(value = "inventory", key = "#name")
+ S save(S s);
}
diff --git a/src/main/java/com/example/crud/repositories/PersonRepository.java b/src/main/java/com/example/crud/repositories/PersonRepository.java
new file mode 100644
index 0000000..384aa33
--- /dev/null
+++ b/src/main/java/com/example/crud/repositories/PersonRepository.java
@@ -0,0 +1,8 @@
+package com.example.crud.repositories;
+
+import com.example.crud.entities.Inventory;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+public interface PersonRepository extends JpaRepository, JpaSpecificationExecutor {
+}
diff --git a/src/main/resources/META-INF/orm.xml b/src/main/resources/META-INF/orm.xml
index 24589d7..cc57e2d 100644
--- a/src/main/resources/META-INF/orm.xml
+++ b/src/main/resources/META-INF/orm.xml
@@ -46,6 +46,7 @@
+
@@ -63,6 +64,9 @@
+
+
+
diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml
index 6036c4f..ff4b3fc 100644
--- a/src/main/resources/META-INF/persistence.xml
+++ b/src/main/resources/META-INF/persistence.xml
@@ -15,7 +15,7 @@
-
+
com.example.crud.entities.Inventory
com.example.crud.entities.Product
com.example.crud.entities.Book
@@ -25,10 +25,12 @@
-
-
-
+
+
+
+
+
diff --git a/src/main/resources/ehcache.xml b/src/main/resources/ehcache.xml
index 1c9f9db..6dbcb6f 100644
--- a/src/main/resources/ehcache.xml
+++ b/src/main/resources/ehcache.xml
@@ -1,13 +1,21 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/infinispan.xml b/src/main/resources/infinispan.xml
deleted file mode 100644
index 083bdfa..0000000
--- a/src/main/resources/infinispan.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
index f8a5427..03e1e30 100644
--- a/src/main/resources/logback.xml
+++ b/src/main/resources/logback.xml
@@ -17,92 +17,58 @@
-
-
-
-
-
+
+ 10000
+ 0
-
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+