Статьи

Приложения Polyglot на OpenShift

Вступление

Платформа как услуга (PaaS) заботится об инфраструктуре, промежуточном программном обеспечении, конфигурации и других проблемах, связанных с платформой, от разработчиков и позволяет им сосредоточиться на своей ключевой компетенции, то есть на разработке и разработке своих доменных приложений. В этой статье я собираюсь продемонстрировать, как с минимальными усилиями создать «приложение Polyglot», включающее хранение и поиск данных в RDBMS и NoSQL.

Что такое приложение Polyglot?

В контексте приложений баз данных приложение полиглот включает в себя постоянство нескольких баз данных. Это несложно, когда задействованные бизнес-объекты хранятся в базах данных РСУБД. Все становится сложным, когда эти базы данных неоднородны по своей природе (например, сочетание различных NoSQL и, возможно, также RDBMS). Возьмем, к примеру, случай пользователей, у которых много адресов. Пользователь должен храниться в MongoDB, а адреса должны храниться в RDBMS.

             (1-M)              
 User       --------->    Address
(MongoDB)                 (MySQL)

Этот вид использования ставит некоторые действительно сложные задачи, такие как:

1. Кривая обучения

Базы данных NoSQL имеют свой собственный API (и есть клиенты высокого уровня). Они имеют длительную кривую обучения, и для их работы обычно требуются разработчики, которые уже имеют опыт работы с ними.

2. Сложность развития

Управление различными бизнес-объектами, которые будут сохранены в гетерогенных системах, представляет собой проблему при разработке на уровне доступа к данным. Ваш код будет использовать разные API, что затруднит разработку, тестирование и поддержку вашего кода.

3. Сложность развертывания

Различные базы данных NoSQL имеют свои собственные настройки, структуру и механизм развертывания. Они должны быть настроены для лучшей производительности и потребностей приложений. Самостоятельное управление этой разнообразной инфраструктурой является сложной задачей с точки зрения затрат и сложности. Поставщик решений должен тратить время на решение бизнес-задач наилучшим образом, а не на решение и борьбу с проблемами, которые ставят эти технологии.

Так что же нам делать?

Первые две из этих проблем могут быть решены с помощью  Kundera  в качестве библиотеки отображения объектного хранилища данных. Кундера поддерживает  постоянство Полиглота и, как мы увидим, это почти не требует усилий для управления различными объектами для разных баз данных. Третья проблема решается с помощью провайдера PaaS. Ваш поставщик PaaS будет отвечать за управление базами данных, аппаратными ресурсами, серверами приложений и т. Д. При разработке приложения. OpenShift от RedHat — это платформа приложений в облаке, где разработчики приложений и команды могут создавать, тестировать, развертывать и запускать свои приложения. OpenShift предоставляет различные «картриджи», которые вы можете добавить в свое приложение в соответствии с вашими потребностями. MongoDB и MySQL среди них. Мы создадим приложение, которое читает и записывает бизнес-объекты в MySQL и MongoDB, используя Kundera.

Давайте готовьтесь

Теперь мы готовы построить наше приложение polyglot, включающее две сущности: User и Address. Пользователь будет храниться в MongoDB, а Адрес в MySQL. Вот шаги, которые вы должны выполнить:

1. Зарегистрируйтесь и войдите в  OpenShift .2. Добавить Java-приложение на основе Tomcat 7 (картридж JBoss EWS 2.0) 3. Добавить картриджи — База данных MongoDB Nosql 2.2 и база данных MySQL 5.14. Напишите ваше приложение NoSQL. Вставьте свой код в Git-репозиторий, созданный в OpenShift. (Артефакты развертываются на серверах автоматически) .6. Протестируйте ваше приложение. 

Регистрация и вход

1. Посетите  веб-сайт https://www.openshift.com/ 2. Нажмите «Зарегистрироваться» и введите данные. Подтвердите и войдите. 

Создать приложение

1. Нажмите Мои приложения -> Добавить приложение2. Выберите Java в раскрывающемся списке.3. Нажмите на Tomcat (JBoss EWS 2.0) 4. Дайте вашему приложению имя и нажмите «Создать приложение».  

Добавить приложение

PaasMongo_Create_Application_2

Добавить картриджи

1. Нажмите Мои приложения -> <Имя вашего приложения> 2. Нажмите «Добавить картридж» 3. Добавьте «MySQL Database 5.1 ″, добавляя этот картридж, запишите учетные данные аутентификации базы данных и имя схемы, лучше сделайте снимок экрана) 4. Повторите вышеуказанный шаг для добавления картриджа «База данных MongoDB NoSQL 2.2».  

PaasMongoAddCartridge

Написать приложение NoSQL

Мы покажем, как написать простое приложение для чтения и записи между хранилищами данных на MySQL и MongoDB.

1. Добавьте зависимости в pom.xml

Add Kundera repositories under repositories tag inside pom.xml:
<repository>
    <id>sonatype-nexus</id>
    <name>Kundera Public Repository</name>
    <url>https://oss.sonatype.org/content/repositories/releases</url>
    <releases>
        <enabled>true</enabled>
    </releases>
    <snapshots>
        <enabled>false</enabled>
    </snapshots>
</repository>
<repository>
    <id>kundera-missing</id>
    <name>Kundera Public Missing Resources Repository</name>
    <url>http://kundera.googlecode.com/svn/maven2/maven-missing-resources</url>
    <releases>
        <enabled>true</enabled>
    </releases>
    <snapshots>
        <enabled>true</enabled>
    </snapshots>
</repository>
Add following dependencies under dependencies tag inside pom.xml:
<dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <version>5.1.6</version>
 </dependency>
 <!-- Kundera Dependency -->
 <dependency>
 <groupId>com.impetus.client</groupId>
 <artifactId>kundera-rdbms</artifactId>
 <version>2.6</version>
 </dependency>
 <dependency>
 <groupId>com.impetus.core</groupId>
 <artifactId>kundera-core</artifactId>
 <version>2.6</version>
 </dependency>
 <dependency>
 <groupId>com.impetus.client</groupId>
 <artifactId>kundera-mongo</artifactId>
 <version>2.6</version>
 </dependency>
 <dependency>
 <groupId>javax.servlet</groupId>
 <artifactId>servlet-api</artifactId>
 <version>2.5</version>
 </dependency>

2. Напишите классы сущностей

User.java

import javax.persistence.CascadeType;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
 
@Entity
@Table(name = "User", schema = "PaaSMongo@mongo-openshift_pu")
public class User {
 @Id
 @Column(name = "ID")
 private int id;
 
@Column(name = "NAME")
 private String name;
 
@Column(name = "AGE")
 private int age;
 
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
 @JoinColumn(name = "ADDRESS_ID")
 private Address address;
 
//Getters and setters omitted
 
}

Address.java

import javax.persistence.Column;
 
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
 
@Entity
@Table(name = "ADDRESS", schema = "PaaSMongo")
public class Address
{
 @Id
 @Column(name = "ADDRESS_ID")
 private String addressId;
 
@Column(name = "STREET")
 private String street;
 
//Getters and setters omitted
 
}

3. Напишите persistence.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
 
https://raw.github.com/impetus-opensource/Kundera/Kundera-2.0.4/kundera-core/src/test/resources/META-INF/persistence_2_0.xsd"
 
 version="2.0">
 <!-- Persistence Units for Twitter application -->
 
<persistence-unit name="mongo-openshift_pu">
 <provider>com.impetus.kundera.KunderaPersistence</provider>
 <class>com.impetus.kundera.mongo.entities.User</class>
 <exclude-unlisted-classes>true</exclude-unlisted-classes>
 <properties>
 <property name="kundera.nodes" value="127.5.210.1" />
 <property name="kundera.port" value="27017" />
 <property name="kundera.keyspace" value="PaaSMongo" />
 <property name="kundera.dialect" value="mongodb" />
 <property name="kundera.client.lookup.class"
 value="com.impetus.client.mongodb.MongoDBClientFactory" />
 <property name="kundera.cache.provider.class"
 value="com.impetus.kundera.cache.ehcache.EhCacheProvider" />
 <property name="kundera.cache.config.resource" value="/ehcache-test.xml" />
 <property name="kundera.username" value="admin" />
 <property name="kundera.password" value="eaGbuGfS1ct4" />
 </properties>
 </persistence-unit>
 
<persistence-unit name="rdbms-openshift_pu">
 <provider>com.impetus.kundera.KunderaPersistence</provider>
 <class>com.impetus.kundera.mongo.entities.Address</class>
 <exclude-unlisted-classes>true</exclude-unlisted-classes>
 <properties>
 <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
 <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
 <property name="hibernate.connection.url" value="jdbc:mysql://127.5.210.1:3306/PaaSMongo" />
 <property name="hibernate.connection.username" value="adminlRwnUcy" />
 <property name="hibernate.connection.password" value="jvsq6w131Y1p" />
 <property name="kundera.client.lookup.class" value="com.impetus.client.rdbms.RDBMSClientFactory" />
 <property name="hibernate.show_sql" value="true" />
 <property name="hibernate.format_sql" value="true" />
 </properties>
 </persistence-unit>
 
</persistence>

4. Напишите web.xml

<?xml version="1.0" encoding="UTF-8"?>
 
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
 metadata-complete="false">
 
<listener>
 
 <listener-class>com.impetus.kundera.mongo.listener.StartUpListener</listener-class>
 </listener>
 
</web-app>

5. Напишите CRUD-операции

OperationHandler.java

import java.util.List;
 
import com.impetus.kundera.mongo.entities.User;
 
public interface OperationHandler
{
 
void saveUser(User user);
 
User findUserById(Class clazz, Object id);
 
List<User> findUserByName(String clazz, String name);
 
List<User> findUserByAge(String clazz, int age);
 
List<User> findAllUser(String clazz);
}

OperationHandlerImpl.java

import java.util.List;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
 
import com.impetus.kundera.mongo.entities.User;
 
public class OperationHandlerImpl implements OperationHandler {
 
private EntityManagerFactory emf;
 
private EntityManager em;
 
@Override
 public void saveUser(User user) {
 getEntityManager();
 em.persist(user);
 }
 
@Override
 public User findUserById(Class clazz, Object id) {
 getEntityManager();
 return em.find(User.class, id);
 }
 
@Override
 public List<User> findUserByName(String clazz, String name) {
 
getEntityManager();
 Query q = em.createQuery("Select u from " + clazz + " u "
 + "where u.name = " + name);
 return q.getResultList();
 
}
 
@Override
 public List<User> findUserByAge(String clazz, int age) {
 getEntityManager();
 Query q = em.createQuery("Select u from " + clazz + " u "
 + "where u.age = " + age);
 return q.getResultList();
 }
 
@Override
 public List<User> findAllUser(String clazz) {
 getEntityManager();
 Query q = em.createQuery("Select u from " + clazz + " u ");
 return q.getResultList();
 }
 
private EntityManager getEntityManager() {
 
if (emf == null) {
 emf = Persistence
 .createEntityManagerFactory("mongo-openshift_pu,rdbms-openshift_pu");
 em = emf.createEntityManager();
 
} else if (em == null) {
 em = emf.createEntityManager();
 }
 return em;
 }
 
public void removeAll(String clazz) {
 getEntityManager();
 Query q = em.createQuery("Delete from " + clazz + " u ");
 }
 
public void close() {
 em.close();
 emf.close();
 }
 
public void clear() {
 em.clear();
 }
}

6. Создать Startup Listener

import javax.servlet.ServletContextEvent;</pre>
import javax.servlet.ServletContextListener;
 
import com.impetus.kundera.mongo.entities.Address;
import com.impetus.kundera.mongo.entities.User;
import com.impetus.kundera.mongo.handler.OperationHandlerForUser;
 
public class StartUpListener implements ServletContextListener {
 OperationHandlerForUser handler = null;
 int userId1;
 int userId2;
 
@Override
 public void contextDestroyed(ServletContextEvent arg0) {
 
 }
 
@Override
 public void contextInitialized(ServletContextEvent arg0) {
 handler = new OperationHandlerImpl();
 persist();
 find();
 }
 
private void persist() {
 Double d = Math.random();
 Long t1 = System.currentTimeMillis();
 Address address1 = new Address();
 address1.setAddressId(t1.toString());
 address1.setStreet("AAAAAAA");
 
Address address2 = new Address();
 address2.setAddressId(t1.toString() + "1");
 address2.setStreet("BBBBBBB");
 
User user1 = new User();
 userId1 = d.intValue();
 user1.setPersonId(d.intValue());
 user1.setPersonName("Kuldeep");
 user1.setAge(24);
 user1.setAddress(address1);
 
User user2 = new User();
 userId2 = d.intValue() + 1;
 user2.setPersonId(d.intValue() + 1);
 user2.setPersonName("Amresh");
 user2.setAge(30);
 user2.setAddress(address2);
 
handler.saveUser(user1);
 handler.saveUser(user2);
 handler.clear();
 
}
 
private void find() {
 User user1 = handler.findUserById(User.class, userId1);
 System.out.println(user1.getPersonName());
 System.out.println(user1.getAge());
 System.out.println(user1.getAddress().getAddressId());
 System.out.println(user1.getAddress().getStreet());
 
User user2 = handler.findUserById(User.class, userId2);
 System.out.println(user2.getPersonName());
 System.out.println(user2.getAge());
 System.out.println(user2.getAddress().getAddressId());
 System.out.println(user2.getAddress().getStreet());
 }
}

Push-код и тестовое приложение

1. Скопируйте ваши открытые ключи в операционной системе в Моя учетная запись -> Открытые ключи2. Клонируйте ваш репозиторий git.3. Зафиксируйте код и нажмите.4. Проверьте данные, записанные в базу данных с консоли MySQL и MongoDB, и проверьте вывод, напечатанный в журналах Tomcat. 

Вывод

Как мы видим, Kundera + Openshift значительно облегчают разработку и развертывание. Все, что нам нужно, это несколько кликов на веб-странице Openshift и простая настройка в persistence.xml. На самом деле мы сосредоточились на написании сущностей и кода CRUD. Kundera также поддерживает  доступ  на основе REST для данных, хранящихся в нескольких хранилищах данных. Для этого необходимо добавить запись сервлета JAX-RS в дескриптор развертывания веб-приложения. Это открывает для вас новую возможность представить свои данные различным приложениям.