Статьи

Использование данных Spring с Apache Camel

Spring Data экономит ваше время, создавая интеллектуальные DAO, которые вы можете получить бесплатно без написания кода. Он в основном следует шаблону репозитория из книги DDD Эрика Эванса и рассматривает сущности как коллекции. Он имеет большое соглашение, которое позволяет вам задавать критерии для сложных запросов и даже использовать API критериев JPA или свободно распространяемые API QueryDSL для еще более сложных запросов / спецификаций. Самое приятное, что абстракция работает не только для JPA, но и для многих других провайдеров . Есть несколько замечательных примеров использования Spring Data в весенней экосистеме, такой как Spring Boot но иногда вы хотите использовать его за пределами волшебного, заколдованного мира Spring Boot.

И если вы занимаетесь какой-либо серьезной системной интеграцией, вы, вероятно, также используете Apache Camel , поэтому в следующем небольшом блоге (обещание) я покажу вам основные детали, которые вам понадобятся при использовании с Camel … однако, ничего нет слишком особенный здесь. Мы в основном разобрали часть магии, за которую Spring Boot иначе позаботится о вас, и позволит вам понять составные части, которые необходимо будет иметь на месте (и это верно, если вы запускаете Tomcat, Dropwizard, Wildfly или любой контейнер).

Пример кода для этого находится здесь, на моем github, для некоторого кода, над которым мы работали .

Первым шагом вам понадобятся зависимости JPA и Spring-data!

<!-- spring data + JPA -->
<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-jpa</artifactId>
</dependency>

<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-commons</artifactId>
</dependency>
<dependency>
  <groupId>org.hibernate.javax.persistence</groupId>
  <artifactId>hibernate-jpa-2.1-api</artifactId>
  <version>1.0.0.Final</version>
</dependency>
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-entitymanager</artifactId>
  <version>${hibernate.version}</version>
</dependency>
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-core</artifactId>
  <version>${hibernate.version}</version>
</dependency>

Это подготовит для нас classpath, который должен включать JPA API и менеджеры сущностей для провайдера, которого мы будем использовать.

Далее мы должны добавить следующее в spring-context / bean-factory:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName" value="org.apache.derby.jdbc.EmbeddedDriver"/>
  <property name="url" value="jdbc:derby:memory:orders;create=true"/>
  <property name="username" value=""/>
  <property name="password" value=""/>
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
  <property name="dataSource" ref="dataSource"/>
</bean>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="dataSource" ref="dataSource"/>
  <property name="persistenceXmlLocation" value="classpath:/META-INF/persistence.xml"/>
  <property name="persistenceUnitName" value="sample"/>
  <!-- spring based scanning for entity classes>-->
  <property name="packagesToScan" value="org.jboss.fuse.examples.rest"/>
</bean>

<bean id="transactionManager"
      class="org.springframework.orm.hibernate4.HibernateTransactionManager">
  <property name="sessionFactory" ref="sessionFactory"/>
  <property name="dataSource" ref="dataSource"/>
</bean>

Все это работает на мельнице Spring ORM ; здесь нет ничего необычного, но это типичный материал, который понадобится для данных о весне.

Чтобы использовать JPA, мы также хотим persistence.xmlфайл. Если вы хотите использовать Mongo или что-то еще, обратитесь к этому конкретному mdoule Spring-data, чтобы узнать, как это сделать.

<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 http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">
  <persistence-unit name="sample">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <properties>
      <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyTenSevenDialect"/>
    </properties>
  </persistence-unit>
</persistence>

Это должно дать нам основу для использования Spring-данных! Теперь давайте сделаем некоторые забавные вещи. Мы добавим репозиторий, который позволит нам выполнять операции CRUD (и даже больше!) Над базой данных:

package org.jboss.fuse.examples.repositories;

import org.jboss.fuse.examples.rest.Organization;
import org.springframework.data.repository.PagingAndSortingRepository;

/**
 * Created by ceposta 
 * <a href="http://christianposta.com/blog>http://christianposta.com/blog</a>.
 */
public interface OrganizationRepository extends PagingAndSortingRepository<Organization, Integer> {

}

У нас есть наш репозиторий, но нам нужно рассказать весне, как его найти и применить магию. Итак, давайте добавим его в контекст Spring следующим образом (и сделаем так, чтобы Spring сканировал пакет, чтобы найти хранилище)

<jpa:repositories base-package="org.jboss.fuse.examples.repositories"/>

Обратите внимание, что для этого потребуются соответствующие пространства имен (предполагается, что мы используем конфигурацию Spring XML; конфигурация java также поддерживается, но здесь не показана):

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xsi:schemaLocation="
          http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
          http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">

Теперь давайте добавим наш репозиторий в наш собственный класс POJO, из которого мы можем его использовать! Вау, вау … «на самом деле мы не написали никакого кода для реализации этого хранилища», говорите вы… да, это правда! Spring-data делает это для нас!

Давайте введем:

<bean id="orgCollection" class="org.jboss.fuse.examples.rest.OrganizationCollection">
  <property name="repository" ref="organizationRepository"/>
</bean>

Обратите внимание, что имя репозитория organizationRepositoryсоздается соглашением к весне, когда оно сканирует пакет на предмет наличия репозиториев, но мы все равно можем взять его и использовать как любой другой Spring Bean на фабрике бинов. Теперь давайте используем этот класс-оболочку ( OrganizationCollectionв данном случае) в наших маршрутах Camel:

<route id="findAll">
  <from uri="direct:findAll"/>
  <bean ref="orgCollection" method="findAll"/>
</route>


<route id="orgById">
  <from uri="direct:orgById"/>
  <bean ref="orgCollection" method="findById"/>
</route>

<route id="paginate">
  <from uri="direct:paginate"/>
  <bean ref="orgCollection" method="findOrganizationWithPagination"/>
</route>

Прохладно! У нас есть 3 отдельных маршрута, которые используют наш pog orgCollection (который, в свою очередь, использует OrganizationRepository, который использует данные Spring). Давайте посмотрим на это POJO:

package org.jboss.fuse.examples.rest;

import org.apache.camel.Header;
import org.apache.camel.language.Simple;
import org.jboss.fuse.examples.repositories.OrganizationRepository;
import org.springframework.data.domain.PageRequest;


public class OrganizationCollection {

    private OrganizationRepository repository;


    public Organization insertNewOrganization(@Simple("body.org_id") Integer id, @Simple("body.org_name") String name) {
        Organization org = new Organization(id, name);
        return repository.save(org);
    }

    public Iterable<Organization> findAll(){
        return repository.findAll();
    }

    public Iterable<Organization> findOrganizationWithPagination(@Header("pageNumber")int pageNum, @Header("pageSize")int size){
        return repository.findAll(new PageRequest(pageNum, size));
    }

    public Organization findById(@Header("id")int id) {
        return repository.findOne(id);
    }

    public OrganizationRepository getRepository() {
        return repository;
    }


    public void setRepository(OrganizationRepository repository) {
        this.repository = repository;
    }
}

Мы внедряем OrganizationRepositoryи используем его здесь для запроса к хранилищу данных. Обратите внимание, что параметры имеют аннотации Apache Camel, которые извлекают значения из заголовков и тела для использования в качестве параметров.