Skip to content

Commit

Permalink
Merge vert-x3#51 - Initial version of spring-vertx example - see READ…
Browse files Browse the repository at this point in the history
…ME.adoc for details
  • Loading branch information
cescoffier committed Jun 15, 2015
2 parents 280b3a4 + 97c8aeb commit 3ddeb4c
Show file tree
Hide file tree
Showing 12 changed files with 425 additions and 0 deletions.
5 changes: 5 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,11 @@ following the two proposed approaches: using the DIY cartridge or the vert.x 3 c
The link:spring-examples[Vert.x Spring Examples] shows how vert.x application can be integrated inside a Spring
ecosystem.

=== Spring example

The link:spring-example/README.adoc[Vert.x Spring Example] shows how you can access Spring beans as services in a vert.x
application

=== Redis example

The link:redis-examples/README.adoc[Vert.x Redis Example] shows how you can interact with Redis using the vert.x redis client.
Expand Down
30 changes: 30 additions & 0 deletions spring-example/README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
= Vert.x 3.0 Spring-vertx example project

This project is a demo of exposing Spring-hosted service beans (and therefore Spring-wired services) via vert.x
verticles. In vert.x 3 it's perfectly possible to share an application context between multiple verticles.

In this case the service bean we expose through vert.x is a trivial data access service running through Spring Data
JPA (and using Hibernate). In effect we're taking advantage of the ease of building data access via Spring/Hibernate
but using vert.x as the connector between external clients and the Spring context.

Note that because we're doing blocking JDBC access, we host the call to the service within an executeBlocking call, to
avoid blocking the event bus.

You can run it directly in your IDE by creating a run configuration that uses the main class
`io.vertx.examples.spring.SpringExampleRunner`.

The pom.xml uses the Maven shade plugin to assemble the application and all it's dependencies into a single "fat" jar.

To build a "fat jar"

mvn package

To run the fat jar:

java -jar target/spring-example-3.0.0-SNAPSHOT-fat.jar

(You can take that jar and run it anywhere there is a Java 8+ JDK. It contains all the dependencies it needs so you
don't need to install Vert.x on the target machine).

Now point your browser at http://localhost:8080 to see a simple welcome page, and then
http://localhost:8080/products to see the Spring-hosted service invoked via the vertx eventbus
104 changes: 104 additions & 0 deletions spring-example/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>

<groupId>io.vertx</groupId>
<artifactId>spring-example</artifactId>
<version>3.0.0-SNAPSHOT</version>
<name>spring-example</name>

<properties>
<!-- the main verticle class name -->
<main.class>io.vertx.examples.spring.SpringExampleRunner</main.class>
<spring.data.jpa.version>1.8.0.RELEASE</spring.data.jpa.version>
<h2.version>1.4.187</h2.version>
<slf4j.version>1.7.12</slf4j.version>
<hibernate.version>4.3.10.Final</hibernate.version>
</properties>

<dependencies>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>${spring.data.jpa.version}</version>
</dependency>

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>

<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>

</dependencies>

<build>
<pluginManagement>
<plugins>
<!-- We specify the Maven compiler plugin as we need to set it to Java 1.8 -->
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>

<!--
You only need the part below if you want to build your application into a fat executable jar.
This is a jar that contains all the dependencies required to run it, so you can just run it with
java -jar
-->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>${main.class}</Main-Class>
</manifestEntries>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/services/io.vertx.core.spi.VerticleFactory</resource>
</transformer>
</transformers>
<artifactSet>
</artifactSet>
<outputFile>${project.build.directory}/${project.artifactId}-${project.version}-fat.jar</outputFile>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.vertx.examples.spring;

import io.vertx.core.Vertx;
import io.vertx.examples.spring.context.ExampleSpringConfiguration;
import io.vertx.examples.spring.verticle.ServerVerticle;
import io.vertx.examples.spring.verticle.SpringDemoVerticle;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
* Runner for the vertx-spring sample
*
*/
public class SpringExampleRunner {

public static void main( String[] args ) {
ApplicationContext context = new AnnotationConfigApplicationContext(ExampleSpringConfiguration.class);
final Vertx vertx = Vertx.vertx();
vertx.deployVerticle(new SpringDemoVerticle(context));
vertx.deployVerticle(new ServerVerticle());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package io.vertx.examples.spring.context;

import org.springframework.beans.factory.annotation.Autowired;
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 org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jdbc.datasource.init.DatabasePopulator;
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.util.Properties;

/**
* Simple Java Spring configuration to be used for the Spring example application. This configuration is mainly
* composed of a database configuration and initial population via the script "products.sql" of the database for
* querying by our Spring service bean.
*
* The Spring service bean and repository are scanned for via @EnableJpaRepositories and @ComponentScan annotations
*/
@Configuration
@EnableJpaRepositories(basePackages = {"io.vertx.examples.spring.repository"})
@PropertySource(value = { "classpath:application.properties" })
@ComponentScan("io.vertx.examples.spring.service")
public class ExampleSpringConfiguration {

@Autowired
private Environment env;

@Bean
@Autowired
public DataSource dataSource(DatabasePopulator populator) {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.username"));
dataSource.setPassword(env.getProperty("jdbc.password"));
DatabasePopulatorUtils.execute(populator, dataSource);
return dataSource;
}

@Bean
@Autowired
public LocalContainerEntityManagerFactoryBean entityManagerFactory(final DataSource dataSource) {
final LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setDataSource(dataSource);
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(Boolean.TRUE); vendorAdapter.setShowSql(Boolean.TRUE);
factory.setDataSource(dataSource);
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("io.vertx.examples.spring.entity");
Properties jpaProperties = new Properties();
jpaProperties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
jpaProperties.put("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
factory.setJpaProperties(jpaProperties);
factory.afterPropertiesSet();
return factory;
}

@Bean
@Autowired
public PlatformTransactionManager transactionManager(LocalContainerEntityManagerFactoryBean entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory.getObject());
}

@Bean
@Autowired
public DatabasePopulator databasePopulator() {
final ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
populator.setContinueOnError(false);
populator.addScript(new ClassPathResource("products.sql"));
return populator;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.vertx.examples.spring.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

/**
* Trivial JPA entity for vertx-spring demo
*/
@Entity
@Table(name="PRODUCT")
public class Product {

@Id
@Column(name="ID")
private Integer productId;

@Column
private String description;

public Integer getProductId() {
return productId;
}

public String getDescription() {
return description;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.vertx.examples.spring.repository;

import io.vertx.examples.spring.entity.Product;
import org.springframework.data.jpa.repository.JpaRepository;

/**
* Spring Data JPA repository to connect our service bean to data
*/
public interface ProductRepository extends JpaRepository<Product, Integer> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.vertx.examples.spring.service;

import io.vertx.examples.spring.entity.Product;
import io.vertx.examples.spring.repository.ProductRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
* Simple Spring service bean to expose the results of a trivial database call
*/
@Service
public class ProductService {

@Autowired
private ProductRepository repo;

public List<Product> getAllProducts() {
return repo.findAll();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package io.vertx.examples.spring.verticle;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServer;

/**
* Simple web server verticle to expose the results of the Spring service bean call (routed via a verticle - see
* SpringDemoVerticle)
*/
public class ServerVerticle extends AbstractVerticle {

@Override
public void start() throws Exception {
super.start();
HttpServer server = vertx.createHttpServer();
server.requestHandler(req -> {
if (req.method() == HttpMethod.GET) {
req.response().setChunked(true);

if (req.path().equals("/products")) {
vertx.eventBus().<String>send(SpringDemoVerticle.ALL_PRODUCTS_ADDRESS, "", result -> {
if (result.succeeded()) {
req.response().setStatusCode(200).write(result.result().body()).end();
} else {
req.response().setStatusCode(500).write(result.cause().toString()).end();
}
});
} else {
req.response().setStatusCode(200).write("Hello from vert.x").end();
}

} else {
// We only support GET for now
req.response().setStatusCode(405).end();
}
});

server.listen(8080);
}
}
Loading

0 comments on commit 3ddeb4c

Please sign in to comment.