Commit 95ac8082963d7d7cccaed9f2b89eba7a902ad999

Authored by Stephan Hausdörfer
2 parents aa62787f 896a9c92

Merge branch 'persistence' into 'development'

merge persistence to development



See merge request !1
Showing 28 changed files with 1118 additions and 4 deletions
.gitignore
... ... @@ -14,10 +14,13 @@ hs_err_pid*
14 14 # Logfiles
15 15 **.log
16 16 **.log.*
  17 +docker/wildfly/volumes/logs/
17 18  
18 19 **/.DS_Store
19 20 .idea
20 21 .gradle
21 22 bht-chatbot.iml
  23 +BeuthBot.iml
22 24 target/
23 25 build
  26 +out
... ...
docker/docker-compose.yml
... ... @@ -9,13 +9,20 @@ services:
9 9 - "8080:8080"
10 10 - "8787:8787"
11 11 - "9990:9990"
  12 + environment:
  13 + POSTGRES_USER: beuthbot_app
  14 + POSTGRES_PASSWORD: VhS7WPVpdYEHYLpf
  15 + POSTGRES_DB: beuthbot
12 16 volumes:
13 17 - ./wildfly/volumes/deployments/:/opt/jboss/wildfly/standalone/deployments/
14 18 - ./wildfly/volumes/logs/:/opt/jboss/wildfly/standalone/log/
15 19 - ./wildfly/volumes/conf/:/opt/jboss/wildfly/standalone/conf/
  20 + - ./wildfly/volumes/modules/org/postgres/main/:/opt/jboss/wildfly/modules/org/postgres/main/
16 21 links:
17 22 - rasa-server
  23 + - postgres-db
18 24 command: /opt/jboss/wildfly/bin/standalone.sh -b 0.0.0.0 -bmanagement 0.0.0.0 --debug
  25 +
19 26 rasa-server:
20 27 build: ./rasa_nlu
21 28 container_name: rasa_nlu
... ... @@ -25,4 +32,22 @@ services:
25 32 volumes:
26 33 - ./rasa_nlu/volumes/data/api/:/app/data/api
27 34 - ./rasa_nlu/volumes/logs/:/app/logs/
28   - command: python -m rasa_nlu.server -c config/chatbot_config.json --server_model_dirs=default
29 35 \ No newline at end of file
  36 + command: python -m rasa_nlu.server -c config/chatbot_config.json --server_model_dirs=default
  37 +
  38 + postgres-db:
  39 + image: postgres
  40 + ports:
  41 + - "5432:5432"
  42 + command: postgres -c logging_collector=on -c log_destination=stderr -c log_directory=/logs
  43 + environment:
  44 + POSTGRES_USER: beuthbot_app
  45 + POSTGRES_PASSWORD: VhS7WPVpdYEHYLpf
  46 + POSTGRES_DB: beuthbot
  47 + volumes:
  48 + - ./postgres/volumes/logs:/logs
  49 +
  50 + adminer:
  51 + container_name: adminer_dbmanagement
  52 + image: adminer
  53 + ports:
  54 + - "8081:8080"
30 55 \ No newline at end of file
... ...
docker/postgres/volumes/logs/README.md 0 → 100644
  1 +## Log Directory
  2 +This is the log directory which will be mounted into the docker postgres container.
0 3 \ No newline at end of file
... ...
docker/wildfly/Dockerfile
1 1 FROM jboss/wildfly:10.1.0.Final
2 2 RUN /opt/jboss/wildfly/bin/add-user.sh admin Admin
3   -COPY standalone.xml /opt/jboss/wildfly/standalone/configuration/standalone.xml
4 3 \ No newline at end of file
  4 +COPY standalone.xml /opt/jboss/wildfly/standalone/configuration/standalone.xml
  5 +
  6 +
  7 +#USER root
  8 +
  9 +#ADD modules/org/postgres/main/postgresql-42.1.4.jar /opt/jboss/wildfly/modules/org/postgres/main/postgresql-42.1.4.jar
  10 +#ADD modules/org/postgres/main/module.xml /opt/jboss/wildfly/modules/org/postgres/main/module.xml
5 11 \ No newline at end of file
... ...
docker/wildfly/standalone.xml
... ... @@ -161,7 +161,7 @@
161 161 <managed-scheduled-executor-service name="default" jndi-name="java:jboss/ee/concurrency/scheduler/default" context-service="default" hung-task-threshold="60000" keepalive-time="3000"/>
162 162 </managed-scheduled-executor-services>
163 163 </concurrent>
164   - <default-bindings context-service="java:jboss/ee/concurrency/context/default" datasource="java:jboss/datasources/ExampleDS" jms-connection-factory="java:jboss/DefaultJMSConnectionFactory" managed-executor-service="java:jboss/ee/concurrency/executor/default" managed-scheduled-executor-service="java:jboss/ee/concurrency/scheduler/default" managed-thread-factory="java:jboss/ee/concurrency/factory/default"/>
  164 + <default-bindings context-service="java:jboss/ee/concurrency/context/default" datasource="java:jboss/datasources/PostgreSQLDS" jms-connection-factory="java:jboss/DefaultJMSConnectionFactory" managed-executor-service="java:jboss/ee/concurrency/executor/default" managed-scheduled-executor-service="java:jboss/ee/concurrency/scheduler/default" managed-thread-factory="java:jboss/ee/concurrency/factory/default"/>
165 165 </subsystem>
166 166 <subsystem xmlns="urn:jboss:domain:ejb3:4.0">
167 167 <session-bean>
... ... @@ -417,6 +417,40 @@
417 417 <client-config name="Standard-Client-Config"/>
418 418 </subsystem>
419 419 <subsystem xmlns="urn:jboss:domain:weld:3.0"/>
  420 +
  421 + <subsystem xmlns="urn:jboss:domain:datasources:2.0">
  422 + <datasources>
  423 + <datasource jta="true" jndi-name="java:jboss/datasources/PostgreSQLDS" pool-name="PostgreSQLDS" enabled="true" use-java-context="true">
  424 + <connection-url>jdbc:postgresql://postgres-db:5432/beuthbot</connection-url>
  425 + <connection-property name="url">jdbc:postgresql://postgres-db:5432/beuthbot</connection-property>
  426 + <connection-property name="databaseName">beuthbot</connection-property>
  427 + <driver>postgresql</driver>
  428 + <security>
  429 + <user-name>beuthbot_app</user-name>
  430 + <password>VhS7WPVpdYEHYLpf</password>
  431 + </security>
  432 + <pool>
  433 + <min-pool-size>5</min-pool-size>
  434 + <initial-pool-size>5</initial-pool-size>
  435 + <max-pool-size>100</max-pool-size>
  436 + <prefill>true</prefill>
  437 + </pool>
  438 + <validation>
  439 + <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker"/>
  440 + <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter"/>
  441 + </validation>
  442 + </datasource>
  443 +
  444 + <drivers>
  445 + <driver name="postgresql" module="org.postgres">
  446 + <driver-class>org.postgresql.Driver</driver-class>
  447 + <xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
  448 + <datasource-class>org.postgresql.ds.PGSimpleDataSource</datasource-class>
  449 + </driver>
  450 + </drivers>
  451 + </datasources>
  452 + </subsystem>
  453 +
420 454 </profile>
421 455  
422 456 <interfaces>
... ...
docker/wildfly/volumes/modules/org/postgres/main/module.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<module xmlns="urn:jboss:module:1.1" name="org.postgres">
  3 + <resources>
  4 + <!--https://jdbc.postgresql.org/download.html-->
  5 + <resource-root path="postgresql-42.1.4.jar"/>
  6 + </resources>
  7 + <dependencies>
  8 + <module name="javax.api"/>
  9 + <module name="javax.transaction.api"/>
  10 + <module name="javax.servlet.api" optional="true"/>
  11 + </dependencies>
  12 +</module>
0 13 \ No newline at end of file
... ...
docker/wildfly/volumes/modules/org/postgres/main/postgresql-42.1.4.jar 0 → 100644
No preview for this file type
services/Common/build.gradle
... ... @@ -9,6 +9,12 @@ dependencies {
9 9 compile "org.jboss.spec:jboss-javaee-7.0:1.1.0.Final",
10 10 "com.google.code.gson:gson:2.8.1",
11 11 "org.slf4j:slf4j-api:1.7.25"
  12 +
  13 + compile group: 'org.postgresql', name: 'postgresql', version: '9.3-1100-jdbc4'
  14 + compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.0.1'
  15 +
  16 + compileOnly group: 'org.hibernate', name: 'hibernate-core', version: '5.2.12.Final'
  17 + compileOnly group: 'org.hibernate', name: 'hibernate-entitymanager', version: '4.3.6.Final'
12 18 }
13 19  
14 20 sourceCompatibility = 1.8
15 21 \ No newline at end of file
... ...
services/Common/src/main/java/de/bht/beuthbot/daos/AppUserDAO.java 0 → 100644
  1 +package de.bht.beuthbot.daos;
  2 +
  3 +import de.bht.beuthbot.model.entities.AppUser;
  4 +
  5 +import javax.ejb.Remote;
  6 +
  7 +/**
  8 + * Created by Benjamin Rühl on 19.12.2017.
  9 + */
  10 +@Remote
  11 +public interface AppUserDAO extends GenericDAO<AppUser, Long> {
  12 +
  13 + AppUser createUser();
  14 +}
... ...
services/Common/src/main/java/de/bht/beuthbot/daos/AppUserDAOImpl.java 0 → 100644
  1 +package de.bht.beuthbot.daos;
  2 +
  3 +import de.bht.beuthbot.model.entities.AppUserImpl;
  4 +import de.bht.beuthbot.model.entities.AppUser;
  5 +
  6 +import javax.ejb.Stateless;
  7 +
  8 +/**
  9 + * Created by Benjamin Rühl on 19.12.2017.
  10 + */
  11 +@Stateless
  12 +public class AppUserDAOImpl extends GenericHibernateDAO<AppUser, AppUserImpl, Long> implements AppUserDAO {
  13 +
  14 + @Override
  15 + public AppUser createUser() {
  16 + return new AppUserImpl();
  17 + }
  18 +}
... ...
services/Common/src/main/java/de/bht/beuthbot/daos/GenericDAO.java 0 → 100644
  1 +package de.bht.beuthbot.daos;
  2 +
  3 +import de.bht.beuthbot.model.entities.EntityBase;
  4 +
  5 +import javax.ejb.Remote;
  6 +import java.io.Serializable;
  7 +import java.util.List;
  8 +
  9 +/**
  10 + * Created by Benjamin Rühl on 19.12.2017.
  11 + */
  12 +@Remote
  13 +public interface GenericDAO<T extends EntityBase, ID extends Serializable> {
  14 +
  15 + T findById(ID id);
  16 +
  17 + List<T> findAll();
  18 +
  19 + T saveOrUpdate(T entity);
  20 +
  21 + void delete(T entity);
  22 +}
... ...
services/Common/src/main/java/de/bht/beuthbot/daos/GenericHibernateDAO.java 0 → 100644
  1 +package de.bht.beuthbot.daos;
  2 +
  3 +import de.bht.beuthbot.model.entities.EntityBase;
  4 +
  5 +import javax.annotation.PostConstruct;
  6 +import javax.ejb.Stateless;
  7 +import javax.persistence.EntityManager;
  8 +import javax.persistence.EntityManagerFactory;
  9 +import javax.persistence.PersistenceContext;
  10 +import javax.persistence.PersistenceUnit;
  11 +import javax.persistence.criteria.CriteriaBuilder;
  12 +import javax.persistence.criteria.CriteriaQuery;
  13 +import javax.persistence.criteria.Predicate;
  14 +import javax.persistence.criteria.Root;
  15 +import java.io.Serializable;
  16 +import java.lang.reflect.ParameterizedType;
  17 +import java.util.List;
  18 +
  19 +/**
  20 + * Created by Benjamin Rühl on 19.12.2017.
  21 + * Base class for DAO implementations using hibernate for persistence.
  22 + * Provides generic functionality for interaction with entities.
  23 + * @param <I> Interface type of entity class
  24 + * @param <T> Implementation type of entity class
  25 + * @param <ID> Type of entity's primary id
  26 + */
  27 +@Stateless
  28 +public class GenericHibernateDAO<I extends EntityBase, T extends I, ID extends Serializable> implements GenericDAO<I, ID> {
  29 +
  30 + private Class<T> entityClass;
  31 +
  32 + @PersistenceUnit(unitName = "PostgresPU")
  33 + private EntityManagerFactory entityManagerFactory;
  34 +
  35 + @PersistenceContext(unitName = "PostgresPU")
  36 + private EntityManager entityManager;
  37 +
  38 + @SuppressWarnings("unchecked cast")
  39 + @PostConstruct
  40 + public void init() {
  41 + if (entityManager == null)
  42 + throw new RuntimeException("EntityManager must not be null");
  43 +
  44 + entityClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1];
  45 + }
  46 +
  47 + public Class<T> getEntityClass() {
  48 + return entityClass;
  49 + }
  50 +
  51 + @Override
  52 + public I findById(ID id) {
  53 + return entityManager.find(getEntityClass(), id);
  54 + }
  55 +
  56 + @Override
  57 + public List<I> findAll() {
  58 + return findByCriteria();
  59 + }
  60 +
  61 + @Override
  62 + public I saveOrUpdate(I entity) {
  63 + entityManager.merge(entity);
  64 + return entity;
  65 + }
  66 +
  67 + @Override
  68 + public void delete(I entity) {
  69 + entityManager.remove(entity);
  70 + }
  71 +
  72 + /**
  73 + * Use this inside subclasses as a convenience method.
  74 + */
  75 + protected List<I> findByCriteria(Predicate... restrictions) {
  76 + CriteriaBuilder builder = entityManager.getCriteriaBuilder();
  77 + CriteriaQuery<T> criteria = builder.createQuery(getEntityClass());
  78 + Root<T> criteriaRoot = criteria.from(getEntityClass());
  79 +
  80 + criteria.select(criteriaRoot);
  81 + criteria.where(restrictions);
  82 +
  83 + List<T> elements = entityManager.createQuery(criteria).getResultList();
  84 + return (List<I>) elements;
  85 + }
  86 +
  87 + protected EntityManager getEntityManager() {
  88 + return entityManager;
  89 + }
  90 +}
... ...
services/Common/src/main/java/de/bht/beuthbot/model/entities/AppUser.java 0 → 100644
  1 +package de.bht.beuthbot.model.entities;
  2 +
  3 +/**
  4 + * Created by Benjamin Rühl on 19.11.2017.
  5 + */
  6 +public interface AppUser extends EntityBase {
  7 +
  8 + void setFacebookUserId(String facebookUserId);
  9 + String getFacebookUserId();
  10 + void setTelegramUserId(String telegramUserId);
  11 + String getTelegramUserId();
  12 + <T extends Object> T getProperty(String propertyName, Class<T> propertyType);
  13 + void setProperty(String propertyName, Object propertyValue);
  14 +}
... ...
services/Common/src/main/java/de/bht/beuthbot/model/entities/AppUserImpl.java 0 → 100644
  1 +package de.bht.beuthbot.model.entities;
  2 +
  3 +import de.bht.beuthbot.persistence.GenericEntityAccessFacade;
  4 +
  5 +import javax.persistence.CascadeType;
  6 +import javax.persistence.Entity;
  7 +import javax.persistence.OneToOne;
  8 +import javax.persistence.Table;
  9 +
  10 +/**
  11 + * Created by Benjamin Rühl on 19.11.2017.
  12 + * Note: This class must not be named "User" except a different table name is provided.
  13 + * Postgres does not support creating a table named "user".
  14 + */
  15 +@Entity
  16 +@Table
  17 +public class AppUserImpl extends EntityBaseImpl implements AppUser {
  18 +
  19 + private String facebookUserId;
  20 +
  21 + private String telegramUserId;
  22 +
  23 + @OneToOne(cascade = CascadeType.ALL)
  24 + private GenericEntity additionalData;
  25 +
  26 + //@Type(type = "JsonMapType")
  27 + //private Map<String, String> additionalData = new HashMap<>();
  28 +
  29 + public AppUserImpl() {
  30 + additionalData = new GenericEntity();
  31 + additionalData.setName("User");
  32 + }
  33 +
  34 + @Override
  35 + public String getFacebookUserId() {
  36 + return facebookUserId;
  37 + }
  38 +
  39 + @Override
  40 + public String getTelegramUserId() {
  41 + return telegramUserId;
  42 + }
  43 +
  44 + @Override
  45 + public <T> T getProperty(String propertyName, Class<T> propertyType) {
  46 + return GenericEntityAccessFacade.getAttribute(additionalData, propertyName, propertyType);
  47 + }
  48 +
  49 + @Override
  50 + public void setProperty(String propertyName, Object propertyValue) {
  51 + GenericEntityAccessFacade.setAttribute(additionalData, propertyName, propertyValue);
  52 + }
  53 +
  54 + //@Override
  55 + /*public <T extends Object> T getProperty(String propertyName, Class<T> propertyType) {
  56 + String propertyValue = additionalData.getOrDefault(propertyName, null);
  57 +
  58 + if (propertyValue == null)
  59 + return null;
  60 +
  61 + return (T) JsonHelper.fromJson(propertyValue, propertyType);
  62 + }*/
  63 +
  64 + //@Override
  65 + /*public void setProperty(String propertyName, Object propertyValue) {
  66 + String valueAsJson = JsonHelper.toJson(propertyValue, propertyValue.getClass());
  67 + additionalData.put(propertyName, valueAsJson);
  68 + }*/
  69 +
  70 + public void setFacebookUserId(String facebookUserId) {
  71 + this.facebookUserId = facebookUserId;
  72 + }
  73 +
  74 + public void setTelegramUserId(String telegramUserId) {
  75 + this.telegramUserId = telegramUserId;
  76 + }
  77 +}
... ...
services/Common/src/main/java/de/bht/beuthbot/model/entities/EntityBase.java 0 → 100644
  1 +package de.bht.beuthbot.model.entities;
  2 +
  3 +import java.io.Serializable;
  4 +import java.util.Date;
  5 +
  6 +/**
  7 + * Created by Benjamin Rühl on 19.11.2017.
  8 + */
  9 +public interface EntityBase extends Serializable {
  10 +
  11 + Long getId();
  12 +
  13 + Date getCreationDate();
  14 +
  15 + Date getUpdateDate();
  16 +}
... ...
services/Common/src/main/java/de/bht/beuthbot/model/entities/EntityBaseImpl.java 0 → 100644
  1 +package de.bht.beuthbot.model.entities;
  2 +
  3 +import de.bht.beuthbot.persistence.JsonMapUserType;
  4 +
  5 +import org.hibernate.annotations.TypeDef;
  6 +
  7 +import javax.persistence.*;
  8 +import java.util.Date;
  9 +import java.util.Objects;
  10 +
  11 +/**
  12 + * Created by Benjamin Rühl on 19.11.2017.
  13 + */
  14 +@MappedSuperclass
  15 +@Access(AccessType.FIELD)
  16 +@TypeDef(name = "JsonMapType", typeClass = JsonMapUserType.class)
  17 +public class EntityBaseImpl implements EntityBase {
  18 +
  19 + @Id
  20 + @GeneratedValue
  21 + protected long id;
  22 +
  23 + @Temporal(TemporalType.TIMESTAMP)
  24 + protected Date creationDate;
  25 +
  26 + @Temporal(TemporalType.TIMESTAMP)
  27 + protected Date updateDate;
  28 +
  29 + @PrePersist
  30 + protected void onCreate() {
  31 + creationDate = new Date();
  32 + }
  33 +
  34 + @PreUpdate
  35 + protected void onUpdate() {
  36 + this.updateDate = new Date();
  37 + }
  38 +
  39 + @Override
  40 + public Long getId() {
  41 + return null;
  42 + }
  43 +
  44 + @Override
  45 + public Date getCreationDate() {
  46 + return creationDate;
  47 + }
  48 +
  49 + @Override
  50 + public Date getUpdateDate() {
  51 + return updateDate;
  52 + }
  53 +
  54 + @Override
  55 + public boolean equals(Object obj) {
  56 + if (this == obj)
  57 + return true;
  58 +
  59 + if (obj == null)
  60 + return false;
  61 +
  62 + if (obj.getClass() != getClass())
  63 + return false;
  64 +
  65 + EntityBaseImpl other = (EntityBaseImpl)obj;
  66 +
  67 + if (other.getId() == 0 && getId() == 0)
  68 + return super.equals(obj);
  69 +
  70 + return Objects.equals(other.getId(), getId());
  71 + }
  72 +
  73 + @Override
  74 + public int hashCode(){
  75 + return Objects.hash(id);
  76 + }
  77 +}
... ...
services/Common/src/main/java/de/bht/beuthbot/model/entities/GenericEntity.java 0 → 100644
  1 +package de.bht.beuthbot.model.entities;
  2 +
  3 +import javax.persistence.CascadeType;
  4 +import javax.persistence.Entity;
  5 +import javax.persistence.OneToMany;
  6 +import javax.persistence.Table;
  7 +import java.util.ArrayList;
  8 +import java.util.List;
  9 +import java.util.stream.Collectors;
  10 +
  11 +/**
  12 + * Created by Benjamin Rühl on 22.12.2017.
  13 + * A generic container entity that holds references to a set of generic attributes which can be specified at runtime.
  14 + * Follows the Entity-Attribute-Value model of database design.
  15 + */
  16 +@Entity
  17 +@Table
  18 +public class GenericEntity extends EntityBaseImpl {
  19 +
  20 + /**
  21 + * name is not mandatory, but can help to identify the entity's purpose for the developer
  22 + */
  23 + private String name;
  24 +
  25 + @OneToMany(cascade = CascadeType.ALL)
  26 + private List<GenericEntityAttribute> attributes = new ArrayList<>();
  27 +
  28 + public String getName() {
  29 + return name;
  30 + }
  31 +
  32 + public void setName(String name) {
  33 + this.name = name;
  34 + }
  35 +
  36 + public List<GenericEntityAttribute> getAttributes() {
  37 + return attributes;
  38 + }
  39 +
  40 + public void setAttribute(GenericEntityAttribute attribute) {
  41 + List<GenericEntityAttribute> existingAttributesForName = this.attributes.stream().filter(a -> a.getName().equals(attribute.getName())).collect(Collectors.toList());
  42 +
  43 + if (!existingAttributesForName.isEmpty())
  44 + getAttributes().removeAll(existingAttributesForName);
  45 +
  46 + this.attributes.add(attribute);
  47 + }
  48 +}
... ...
services/Common/src/main/java/de/bht/beuthbot/model/entities/GenericEntityAttribute.java 0 → 100644
  1 +package de.bht.beuthbot.model.entities;
  2 +
  3 +import javax.persistence.CascadeType;
  4 +import javax.persistence.Entity;
  5 +import javax.persistence.OneToMany;
  6 +import javax.persistence.Table;
  7 +import java.util.List;
  8 +
  9 +/**
  10 + * Created by Benjamin Rühl on 22.12.2017.
  11 + * An attribute of a generic entity that can be specified at runtime.
  12 + * Holds a collection of generic values.
  13 + */
  14 +@Entity
  15 +@Table
  16 +public class GenericEntityAttribute extends EntityBaseImpl {
  17 +
  18 + private String name;
  19 +
  20 + @OneToMany(cascade = CascadeType.ALL)
  21 + private List<GenericEntityAttributeValue> values;
  22 +
  23 + public String getName() {
  24 + return name;
  25 + }
  26 +
  27 + public void setName(String name) {
  28 + this.name = name;
  29 + }
  30 +
  31 + public List<GenericEntityAttributeValue> getValues() {
  32 + return values;
  33 + }
  34 +
  35 + public void addValue(GenericEntityAttributeValue value) {
  36 + this.values.add(value);
  37 + }
  38 +}
... ...
services/Common/src/main/java/de/bht/beuthbot/model/entities/GenericEntityAttributeValue.java 0 → 100644
  1 +package de.bht.beuthbot.model.entities;
  2 +
  3 +import javax.persistence.CascadeType;
  4 +import javax.persistence.Entity;
  5 +import javax.persistence.OneToOne;
  6 +import javax.persistence.Table;
  7 +
  8 +/**
  9 + * Created by Benjamin Rühl on 22.12.2017.
  10 + * The value of a generic attribute in supported data formats.
  11 + * Supports complex nested types using a reference to a generic sub entity.
  12 + */
  13 +@Entity
  14 +@Table
  15 +public class GenericEntityAttributeValue extends EntityBaseImpl {
  16 +
  17 + private Boolean valueAsBool;
  18 +
  19 + private Long valueAsLong;
  20 +
  21 + private Double valueAsDouble;
  22 +
  23 + private String valueAsString;
  24 +
  25 + @OneToOne(cascade = CascadeType.ALL)
  26 + private GenericEntity valueAsEntity;
  27 +
  28 + public Boolean getValueAsBool() {
  29 + return valueAsBool;
  30 + }
  31 +
  32 + public void setValueAsBool(boolean valueAsBool) {
  33 + this.valueAsBool = valueAsBool;
  34 + }
  35 +
  36 + public Long getValueAsLong() {
  37 + return valueAsLong;
  38 + }
  39 +
  40 + public void setValueAsLong(long valueAsLong) {
  41 + this.valueAsLong = valueAsLong;
  42 + }
  43 +
  44 + public Double getValueAsDouble() {
  45 + return valueAsDouble;
  46 + }
  47 +
  48 + public void setValueAsDouble(double valueAsDouble) {
  49 + this.valueAsDouble = valueAsDouble;
  50 + }
  51 +
  52 + public String getValueAsString() {
  53 + return valueAsString;
  54 + }
  55 +
  56 + public void setValueAsString(String valueAsString) {
  57 + this.valueAsString = valueAsString;
  58 + }
  59 +
  60 + public GenericEntity getValueAsEntity() {
  61 + return valueAsEntity;
  62 + }
  63 +
  64 + public void setValueAsEntity(GenericEntity valueAsEntity) {
  65 + this.valueAsEntity = valueAsEntity;
  66 + }
  67 +}
... ...
services/Common/src/main/java/de/bht/beuthbot/persistence/ExtendedPostgreSQLDialect.java 0 → 100644
  1 +package de.bht.beuthbot.persistence;
  2 +
  3 +import org.hibernate.dialect.PostgreSQLDialect;
  4 +
  5 +import java.sql.Types;
  6 +
  7 +public class ExtendedPostgreSQLDialect extends PostgreSQLDialect {
  8 +
  9 + public ExtendedPostgreSQLDialect(){
  10 + super();
  11 + registerHibernateType(Types.JAVA_OBJECT, "json");
  12 +
  13 + }
  14 +}
0 15 \ No newline at end of file
... ...
services/Common/src/main/java/de/bht/beuthbot/persistence/GenericEntityAccessFacade.java 0 → 100644
  1 +package de.bht.beuthbot.persistence;
  2 +
  3 +import com.fasterxml.jackson.databind.ObjectMapper;
  4 +import com.fasterxml.jackson.databind.module.SimpleModule;
  5 +
  6 +import de.bht.beuthbot.model.entities.GenericEntity;
  7 +import de.bht.beuthbot.model.entities.GenericEntityAttribute;
  8 +
  9 +import java.io.IOException;
  10 +import java.util.List;
  11 +import java.util.stream.Collectors;
  12 +
  13 +/**
  14 + * Created by Benjamin Rühl on 22.12.2017.
  15 + * Provides convenience methods for accessing GenericEntity structures
  16 + */
  17 +public class GenericEntityAccessFacade {
  18 +
  19 + public static <T> T getAttribute(GenericEntity contextEntity, String attributeName, Class<T> attributeType) {
  20 + List<GenericEntityAttribute> propertiesWithName = contextEntity.getAttributes().stream().filter(a -> a.getName().equals(attributeName)).limit(1).collect(Collectors.toList());
  21 +
  22 + if (propertiesWithName == null || propertiesWithName.isEmpty())
  23 + return null;
  24 +
  25 + GenericEntityAttribute property = propertiesWithName.get(0);
  26 +
  27 + try {
  28 + String propertyAsJson = GenericEntityJsonConverter.toJson(property);
  29 + return (T) JsonHelper.fromJson(propertyAsJson, attributeType);
  30 + } catch (IOException e) {
  31 + e.printStackTrace();
  32 + }
  33 +
  34 + return null;
  35 + }
  36 +
  37 + public static void setAttribute(GenericEntity contextEntity, String attributeName, Object attributeValue) {
  38 + String attributeValueAsJson = JsonHelper.toJson(attributeValue, attributeValue.getClass());
  39 +
  40 + GenericEntityAttribute deserializedGenericAttribute = null;
  41 +
  42 + try {
  43 + deserializedGenericAttribute = createGenericEntityAttributeFromJson(attributeValueAsJson);
  44 + } catch (IOException e) {
  45 + e.printStackTrace();
  46 + }
  47 +
  48 + if (deserializedGenericAttribute == null)
  49 + return;
  50 +
  51 + deserializedGenericAttribute.setName(attributeName);
  52 +
  53 + contextEntity.setAttribute(deserializedGenericAttribute);
  54 + }
  55 +
  56 + private static GenericEntityAttribute createGenericEntityAttributeFromJson(String json) throws IOException {
  57 + ObjectMapper mapper = new ObjectMapper();
  58 + SimpleModule module = new SimpleModule();
  59 + module.addDeserializer(GenericEntity.class, new GenericEntityDeserializer());
  60 + module.addDeserializer(GenericEntityAttribute.class, new GenericEntityAttributeDeserializer());
  61 + mapper.registerModule(module);
  62 +
  63 + return mapper.readValue(json, GenericEntityAttribute.class);
  64 + }
  65 +}
... ...
services/Common/src/main/java/de/bht/beuthbot/persistence/GenericEntityAttributeDeserializer.java 0 → 100644
  1 +package de.bht.beuthbot.persistence;
  2 +
  3 +import com.fasterxml.jackson.core.JsonParser;
  4 +import com.fasterxml.jackson.core.JsonProcessingException;
  5 +import com.fasterxml.jackson.core.JsonToken;
  6 +import com.fasterxml.jackson.databind.DeserializationContext;
  7 +import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
  8 +
  9 +import de.bht.beuthbot.model.entities.GenericEntity;
  10 +import de.bht.beuthbot.model.entities.GenericEntityAttribute;
  11 +import de.bht.beuthbot.model.entities.GenericEntityAttributeValue;
  12 +
  13 +import javax.naming.OperationNotSupportedException;
  14 +import java.io.IOException;
  15 +import java.util.ArrayList;
  16 +import java.util.List;
  17 +
  18 +/**
  19 + * Created by Benjamin Rühl on 22.12.2017.
  20 + */
  21 +public class GenericEntityAttributeDeserializer extends StdDeserializer<GenericEntityAttribute> {
  22 +
  23 + public GenericEntityAttributeDeserializer() {
  24 + this(GenericEntityAttribute.class);
  25 + }
  26 +
  27 + public GenericEntityAttributeDeserializer(Class<? extends GenericEntityAttribute> t) {
  28 + super(t);
  29 + }
  30 +
  31 + @Override
  32 + public GenericEntityAttribute deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
  33 + if (jp.isClosed())
  34 + return null;
  35 +
  36 + GenericEntityAttribute deserializedAttribute = new GenericEntityAttribute();
  37 +
  38 + JsonToken jsonToken = jp.getCurrentToken();
  39 +
  40 + if (jsonToken.equals(JsonToken.FIELD_NAME)) {
  41 + String fieldName = jp.getCurrentName();
  42 + deserializedAttribute.setName(fieldName);
  43 +
  44 + jsonToken = jp.nextToken();
  45 +
  46 + if (jsonToken.equals(JsonToken.START_ARRAY)) {
  47 + try {
  48 + for (GenericEntityAttributeValue attributeValue : readAttributeValuesUntilArrayEndToken(jp, ctxt)) {
  49 + deserializedAttribute.addValue(attributeValue);
  50 + }
  51 + } catch (OperationNotSupportedException e) {
  52 + e.printStackTrace();
  53 + }
  54 + } else {
  55 + deserializedAttribute.addValue(readAttributeValueFromCurrentToken(jp, ctxt));
  56 + }
  57 + }
  58 +
  59 + return deserializedAttribute;
  60 + }
  61 +
  62 + private List<GenericEntityAttributeValue> readAttributeValuesUntilArrayEndToken(JsonParser jp, DeserializationContext ctxt) throws IOException, OperationNotSupportedException {
  63 + List<GenericEntityAttributeValue> attributes = new ArrayList<>();
  64 + JsonToken jsonToken = jp.getCurrentToken();
  65 +
  66 + if (!jsonToken.equals(JsonToken.START_ARRAY))
  67 + throw new OperationNotSupportedException("Method should not be called if current token is not START_ARRAY");
  68 +
  69 + while (!jp.isClosed() || jsonToken.equals(JsonToken.END_ARRAY)) {
  70 + jsonToken = jp.nextToken();
  71 + attributes.add(readAttributeValueFromCurrentToken(jp, ctxt));
  72 + }
  73 +
  74 + return attributes;
  75 + }
  76 +
  77 + private GenericEntityAttributeValue readAttributeValueFromCurrentToken(JsonParser jp, DeserializationContext ctxt) throws IOException {
  78 + GenericEntityAttributeValue attributeValue = new GenericEntityAttributeValue();
  79 + JsonToken jsonToken = jp.getCurrentToken();
  80 +
  81 + if (jsonToken.equals(JsonToken.VALUE_FALSE) || jsonToken.equals(JsonToken.VALUE_TRUE)) {
  82 + attributeValue.setValueAsBool(jp.getBooleanValue());
  83 + } else if (jsonToken.equals(JsonToken.VALUE_NUMBER_INT)) {
  84 + attributeValue.setValueAsLong(jp.getLongValue());
  85 + } else if (jsonToken.equals(JsonToken.VALUE_NUMBER_FLOAT)) {
  86 + attributeValue.setValueAsDouble(jp.getFloatValue());
  87 + } else if (jsonToken.equals(JsonToken.VALUE_STRING)) {
  88 + attributeValue.setValueAsString(jp.getText());
  89 + } else if (jsonToken.equals(JsonToken.START_OBJECT)) {
  90 + GenericEntity embeddedEntity = new GenericEntityDeserializer().deserialize(jp, ctxt);
  91 + attributeValue.setValueAsEntity(embeddedEntity);
  92 + }
  93 +
  94 + return attributeValue;
  95 + }
  96 +}
... ...
services/Common/src/main/java/de/bht/beuthbot/persistence/GenericEntityDeserializer.java 0 → 100644
  1 +package de.bht.beuthbot.persistence;
  2 +
  3 +import com.fasterxml.jackson.core.JsonParser;
  4 +import com.fasterxml.jackson.core.JsonProcessingException;
  5 +import com.fasterxml.jackson.core.JsonToken;
  6 +import com.fasterxml.jackson.databind.DeserializationContext;
  7 +import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
  8 +
  9 +import de.bht.beuthbot.model.entities.GenericEntity;
  10 +import de.bht.beuthbot.model.entities.GenericEntityAttribute;
  11 +
  12 +import java.io.IOException;
  13 +
  14 +/**
  15 + * Created by Benjamin Rühl on 23.12.2017.
  16 + */
  17 +public class GenericEntityDeserializer extends StdDeserializer<GenericEntity> {
  18 +
  19 + public GenericEntityDeserializer() {
  20 + this(GenericEntity.class);
  21 + }
  22 +
  23 + public GenericEntityDeserializer(Class<? extends GenericEntity> t) {
  24 + super(t);
  25 + }
  26 +
  27 + @Override
  28 + public GenericEntity deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
  29 + GenericEntity deserializedEntity = new GenericEntity();
  30 + GenericEntityAttributeDeserializer attributeDeserializer = new GenericEntityAttributeDeserializer();
  31 +
  32 + while (!jp.isClosed()) {
  33 + JsonToken jsonToken = jp.nextToken();
  34 +
  35 + if (jsonToken.equals(JsonToken.FIELD_NAME)) {
  36 + GenericEntityAttribute attribute = attributeDeserializer.deserialize(jp, ctxt);
  37 + deserializedEntity.setAttribute(attribute);
  38 + }
  39 + }
  40 +
  41 + return deserializedEntity;
  42 + }
  43 +}
0 44 \ No newline at end of file
... ...
services/Common/src/main/java/de/bht/beuthbot/persistence/GenericEntityJsonConverter.java 0 → 100644
  1 +package de.bht.beuthbot.persistence;
  2 +
  3 +import com.fasterxml.jackson.core.JsonFactory;
  4 +import com.fasterxml.jackson.core.JsonGenerator;
  5 +
  6 +import de.bht.beuthbot.model.entities.GenericEntity;
  7 +import de.bht.beuthbot.model.entities.GenericEntityAttribute;
  8 +import de.bht.beuthbot.model.entities.GenericEntityAttributeValue;
  9 +
  10 +import java.io.IOException;
  11 +import java.io.StringWriter;
  12 +import java.lang.reflect.Field;
  13 +import java.lang.reflect.ParameterizedType;
  14 +import java.lang.reflect.Type;
  15 +import java.util.Arrays;
  16 +import java.util.List;
  17 +
  18 +/**
  19 + * Created by Benjamin Rühl on 22.12.2017.
  20 + * Helper class to serialize GenericEntity as if its generic attributes were normal fields
  21 + */
  22 +public class GenericEntityJsonConverter {
  23 +
  24 + /**
  25 + * Serializes a GenericEntity to json as if its generic attributes were normal fields.
  26 + * Other normal fields are serialized as well.
  27 + * @param genericEntity the context entity to be serialized with all its sub structure
  28 + * @return a serialized string in json format
  29 + * @throws IOException
  30 + */
  31 + public static String toJson(GenericEntity genericEntity) throws IOException {
  32 + JsonFactory jFactory = new JsonFactory();
  33 + StringWriter writer = new StringWriter();
  34 + JsonGenerator jsonGenerator = jFactory.createJsonGenerator(writer);
  35 +
  36 + jsonGenerator.writeStartObject();
  37 + writeGenericEntityWithoutStart(jsonGenerator, genericEntity);
  38 +
  39 + jsonGenerator.close();
  40 + return writer.toString();
  41 + }
  42 +
  43 + /**
  44 + * Serializes a GenericEntityAttribute to json as if it would be a normal field.
  45 + * @param genericAttribute the context attribute to be serialized with all its sub structure
  46 + * @return a serialized string in json format
  47 + * @throws IOException
  48 + */
  49 + public static String toJson(GenericEntityAttribute genericAttribute) throws IOException {
  50 + JsonFactory jFactory = new JsonFactory();
  51 + StringWriter writer = new StringWriter();
  52 + JsonGenerator jsonGenerator = jFactory.createJsonGenerator(writer);
  53 +
  54 + writeGenericAttribute(jsonGenerator, genericAttribute);
  55 +
  56 + jsonGenerator.close();
  57 + return writer.toString();
  58 + }
  59 +
  60 + /**
  61 + * Uses a JsonGenerator to append a GenericEntity and its content to json.
  62 + * Does not open the json object because this part depends on whether the object stands for itself or is the value of a field.
  63 + * However it does close the object.
  64 + * @param jsonGenerator the generator used for building the json
  65 + * @param genericEntity the context entity that is serialized
  66 + * @throws IOException
  67 + */
  68 + private static void writeGenericEntityWithoutStart(JsonGenerator jsonGenerator, GenericEntity genericEntity) throws IOException {
  69 + writeClassFieldsWithoutGenericEntityHierarchy(jsonGenerator, genericEntity);
  70 +
  71 + for (GenericEntityAttribute genericAttribute : genericEntity.getAttributes()) {
  72 + writeGenericAttribute(jsonGenerator, genericAttribute);
  73 + }
  74 +
  75 + jsonGenerator.writeEndObject();
  76 + }
  77 +
  78 + private static void writeGenericAttribute(JsonGenerator jsonGenerator, GenericEntityAttribute genericAttribute) throws IOException {
  79 + List<GenericEntityAttributeValue> attributeValues = genericAttribute.getValues();
  80 +
  81 + if (attributeValues == null || attributeValues.isEmpty()) {
  82 + jsonGenerator.writeNullField(genericAttribute.getName());
  83 + } else if (attributeValues.size() == 1) {
  84 + writeGenericAttributeValue(jsonGenerator, genericAttribute.getValues().get(0), genericAttribute.getName());
  85 + } else {
  86 + writeGenericAttributeMultiValue(jsonGenerator, genericAttribute);
  87 + }
  88 + }
  89 +
  90 + private static void writeGenericAttributeMultiValue(JsonGenerator jsonGenerator, GenericEntityAttribute genericAttribute) throws IOException {
  91 + jsonGenerator.writeArrayFieldStart(genericAttribute.getName());
  92 +
  93 + for (GenericEntityAttributeValue genericValue : genericAttribute.getValues()) {
  94 + writeGenericAttributeValueInArray(jsonGenerator, genericValue);
  95 + }
  96 +
  97 + jsonGenerator.writeEndArray();
  98 + }
  99 +
  100 + private static void writeGenericAttributeValue(JsonGenerator jsonGenerator, GenericEntityAttributeValue genericAttributeValue, String attributeName) throws IOException {
  101 + if (genericAttributeValue.getValueAsBool() != null) {
  102 + jsonGenerator.writeBooleanField(attributeName, genericAttributeValue.getValueAsBool());
  103 + } else if (genericAttributeValue.getValueAsLong() != null) {
  104 + jsonGenerator.writeNumberField(attributeName, genericAttributeValue.getValueAsLong());
  105 + } else if (genericAttributeValue.getValueAsDouble() != null) {
  106 + jsonGenerator.writeNumberField(attributeName, genericAttributeValue.getValueAsDouble());
  107 + } else if (genericAttributeValue.getValueAsString() != null) {
  108 + jsonGenerator.writeStringField(attributeName, genericAttributeValue.getValueAsString());
  109 + } else if (genericAttributeValue.getValueAsEntity() != null) {
  110 + jsonGenerator.writeObjectFieldStart(attributeName);
  111 + writeGenericEntityWithoutStart(jsonGenerator, genericAttributeValue.getValueAsEntity());
  112 + }
  113 + }
  114 +
  115 + private static void writeGenericAttributeValueInArray(JsonGenerator jsonGenerator, GenericEntityAttributeValue genericAttributeValue) throws IOException {
  116 + if (genericAttributeValue.getValueAsBool() != null) {
  117 + jsonGenerator.writeBoolean(genericAttributeValue.getValueAsBool());
  118 + } else if (genericAttributeValue.getValueAsLong() != null) {
  119 + jsonGenerator.writeNumber(genericAttributeValue.getValueAsLong());
  120 + } else if (genericAttributeValue.getValueAsDouble() != null) {
  121 + jsonGenerator.writeNumber(genericAttributeValue.getValueAsDouble());
  122 + } else if (genericAttributeValue.getValueAsString() != null) {
  123 + jsonGenerator.writeString(genericAttributeValue.getValueAsString());
  124 + } else if (genericAttributeValue.getValueAsEntity() != null) {
  125 + jsonGenerator.writeStartObject();
  126 + writeGenericEntityWithoutStart(jsonGenerator, genericAttributeValue.getValueAsEntity());
  127 + }
  128 + }
  129 +
  130 + /**
  131 + * Uses a JsonGenerator to append all fields and their values of the targetObject to json.
  132 + * Ignores fields that have GenericEntity, GenericEntityAttribute or GenericEntityAttributeValue as type or generic list parameter.
  133 + * @throws IOException
  134 + */
  135 + private static void writeClassFieldsWithoutGenericEntityHierarchy(JsonGenerator jsonGenerator, Object targetObject) throws IOException {
  136 + for (Field field : targetObject.getClass().getFields()) {
  137 + if (isGenericEntityHierarchyType(field))
  138 + continue;
  139 +
  140 + try {
  141 + jsonGenerator.writeObjectField(field.getName(), field.get(targetObject));
  142 + } catch (Exception e) {
  143 + jsonGenerator.writeStringField(field.getName(), e.getClass().getName());
  144 + e.printStackTrace();
  145 + }
  146 + }
  147 + }
  148 +
  149 + /**
  150 + * Determines whether the field's type is GenericEntity, GenericEntityAttribute or GenericEntityAttributeValue
  151 + * or a list type with one of those types as generic type parameter.
  152 + */
  153 + private static boolean isGenericEntityHierarchyType(Field field) {
  154 + List<Class> typesOfGenericEntityHierarchy = Arrays.asList(GenericEntity.class, GenericEntityAttribute.class, GenericEntityAttributeValue.class);
  155 +
  156 + // check for list types
  157 + try {
  158 + if (Iterable.class.isAssignableFrom(field.getType())) {
  159 + Type fieldFirstGenericType = ((ParameterizedType)field.getGenericType()).getActualTypeArguments()[0];
  160 + if (typesOfGenericEntityHierarchy.contains(fieldFirstGenericType.getClass()))
  161 + return true;
  162 + }
  163 + } catch (Exception e) {
  164 + // not a list or not generic
  165 + }
  166 +
  167 + return typesOfGenericEntityHierarchy.contains(field.getType());
  168 + }
  169 +}
... ...
services/Common/src/main/java/de/bht/beuthbot/persistence/JsonHelper.java 0 → 100644
  1 +package de.bht.beuthbot.persistence;
  2 +
  3 +import com.google.gson.Gson;
  4 +import com.google.gson.GsonBuilder;
  5 +
  6 +/**
  7 + * Created by Benjamin Rühl on 03.12.2017.
  8 + * A simple wrapper around the json serializer to make sure the same serializer is used across different classes
  9 + */
  10 +public class JsonHelper {
  11 +
  12 + private static final Gson gson = new GsonBuilder().serializeNulls().create();
  13 +
  14 + public static Object fromJson(String json, Class sourceClass) {
  15 + return gson.fromJson(json, sourceClass);
  16 + }
  17 +
  18 + public static String toJson(Object source, Class sourceClass) {
  19 + return gson.toJson(source, sourceClass);
  20 + }
  21 +}
... ...
services/Common/src/main/java/de/bht/beuthbot/persistence/JsonMapUserType.java 0 → 100644
  1 +package de.bht.beuthbot.persistence;
  2 +
  3 +import org.hibernate.HibernateException;
  4 +import org.hibernate.engine.spi.SharedSessionContractImplementor;
  5 +import org.hibernate.internal.util.compare.EqualsHelper;
  6 +import org.hibernate.type.SerializationException;
  7 +import org.hibernate.usertype.UserType;
  8 +import org.postgresql.util.PGobject;
  9 +
  10 +import java.io.Serializable;
  11 +import java.sql.PreparedStatement;
  12 +import java.sql.ResultSet;
  13 +import java.sql.SQLException;
  14 +import java.sql.Types;
  15 +import java.util.HashMap;
  16 +import java.util.Map;
  17 +
  18 +/**
  19 + * Created by Benjamin Rühl on 03.12.2017.
  20 + * Custom Hibernate UserType for mapping json typed columns in postgres to java maps
  21 + * @see <a href="http://vojtechruzicka.com/postgresqls-jsonb-type-mapping-using-hibernate/">vojtechruzicka.com</a>
  22 + */
  23 +public class JsonMapUserType implements UserType {
  24 +
  25 + @Override
  26 + public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException {
  27 + if (value == null) {
  28 + st.setNull(index, Types.OTHER);
  29 + } else {
  30 + st.setObject(index, JsonHelper.toJson(value, Map.class), Types.OTHER);
  31 + }
  32 + }
  33 +
  34 + @Override
  35 + public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException {
  36 + PGobject o = (PGobject) rs.getObject(names[0]);
  37 + if (o.getValue() != null) {
  38 + return JsonHelper.fromJson(o.getValue(), Map.class);
  39 + }
  40 +
  41 + return new HashMap<String, String>();
  42 + }
  43 +
  44 + @Override
  45 + public Object deepCopy(Object originalValue) throws HibernateException {
  46 + if (originalValue == null) {
  47 + return null;
  48 + }
  49 +
  50 + if (!(originalValue instanceof Map)) {
  51 + return null;
  52 + }
  53 +
  54 + Map<String, String> resultMap = new HashMap<>();
  55 +
  56 + Map<?, ?> tempMap = (Map<?, ?>) originalValue;
  57 + tempMap.forEach((key, value) -> resultMap.put((String) key, (String) value));
  58 +
  59 + return resultMap;
  60 + }
  61 +
  62 + @Override
  63 + public Serializable disassemble(Object value) throws HibernateException {
  64 + Object copy = deepCopy(value);
  65 +
  66 + if (copy instanceof Serializable) {
  67 + return (Serializable) copy;
  68 + }
  69 +
  70 + throw new SerializationException(String.format("Cannot serialize '%s', %s is not Serializable.", value, value.getClass()), null);
  71 + }
  72 +
  73 + @Override
  74 + public Object assemble(Serializable cached, Object owner) throws HibernateException {
  75 + return deepCopy(cached);
  76 + }
  77 +
  78 + @Override
  79 + public Object replace(Object original, Object target, Object owner) throws HibernateException {
  80 + return deepCopy(original);
  81 + }
  82 +
  83 + @Override
  84 + public boolean isMutable() {
  85 + return true;
  86 + }
  87 +
  88 + @Override
  89 + public int hashCode(Object x) throws HibernateException {
  90 + if (x == null) {
  91 + return 0;
  92 + }
  93 +
  94 + return x.hashCode();
  95 + }
  96 +
  97 + @Override
  98 + public boolean equals(Object x, Object y) throws HibernateException {
  99 + return EqualsHelper.equals(x, y);
  100 + }
  101 +
  102 + @Override
  103 + public Class<?> returnedClass() {
  104 + return Map.class;
  105 + }
  106 +
  107 + @Override
  108 + public int[] sqlTypes() {
  109 + return new int[]{Types.JAVA_OBJECT};
  110 + }
  111 +}
... ...
services/Common/src/main/resources/META-INF/persistence.xml 0 → 100644
  1 +<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
  2 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3 + xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
  4 + http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
  5 + version="2.1">
  6 +
  7 + <persistence-unit name="PostgresPU" transaction-type="JTA">
  8 +
  9 + <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
  10 +
  11 + <jta-data-source>java:jboss/datasources/PostgreSQLDS</jta-data-source>
  12 +
  13 + <properties>
  14 +
  15 + <!--<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>--> <!-- DB Dialect -->
  16 + <property name="hibernate.dialect" value="de.bht.beuthbot.persistence.ExtendedPostgreSQLDialect"/>
  17 + <!--<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>-->
  18 + <property name="hibernate.hbm2ddl.auto" value="create-drop" /> <!-- create / create-drop / update / none -->
  19 + <property name="hibernate.archive.autodetection" value="class"/>
  20 +
  21 + <property name="hibernate.show_sql" value="true" /> <!-- Show SQL in console -->
  22 + <property name="hibernate.format_sql" value="true" /> <!-- Show SQL formatted -->
  23 + </properties>
  24 +
  25 + </persistence-unit>
  26 +
  27 +</persistence>
0 28 \ No newline at end of file
... ...
services/Global/build.gradle
... ... @@ -13,7 +13,6 @@ dependencies {
13 13 "org.apache.httpcomponents:httpclient:4.5.3",
14 14 "commons-io:commons-io:2.5"
15 15  
16   -
17 16 providedCompile "org.slf4j:slf4j-api:1.7.25"
18 17  
19 18 testCompile "org.jboss.arquillian.junit:arquillian-junit-container:1.1.13.Final",
... ...