Enterprise Development with What needs to be done to run JEE like - - PowerPoint PPT Presentation

enterprise development
SMART_READER_LITE
LIVE PREVIEW

Enterprise Development with What needs to be done to run JEE like - - PowerPoint PPT Presentation

Enterprise Development with What needs to be done to run JEE like applications inside Karaf? @anierbeck - Karaf PMC, Apache Member - OPS4j Pax Web Project Lead - Senior IT Consultant @codecentric - co-Author of Apache Karaf Cookbook 3


slide-1
SLIDE 1

Enterprise Development

with …

slide-2
SLIDE 2

What needs to be done to run JEE like applications inside Karaf?

slide-3
SLIDE 3

2014-­‑10-­‑23 3

@anierbeck

  • Karaf PMC, Apache Member
  • OPS4j Pax Web Project Lead
  • Senior IT Consultant @codecentric
  • co-Author of Apache Karaf Cookbook
slide-4
SLIDE 4

Agenda

  • Enterprise Requirements
  • OSGi with Karaf
  • Enterprise Requirements on Karaf
  • Specialties
  • Http Service
  • Cellar - or how to cluster Karaf
  • Summary

2014-­‑10-­‑23 4

slide-5
SLIDE 5

Enterprise Requirements

slide-6
SLIDE 6

Enterprise Java

2014-­‑10-­‑23 6

Servlet 3 JSF 2 JSP JPA 2 JTA CDI EJB 3.1 Bean Validation JAX-WS JAX-RS JAXR JAXB JMS JAAS JASPIC JACC JSR-88 JCA JavaMail JSR-77 RMI JNDI JAX-RPC SAAJ

slide-7
SLIDE 7

OSGi with Karaf

slide-8
SLIDE 8

OSGi - a very brief introduction

  • Modular
  • OSGi Bundles:
  • High Cohesion (One classloader/bundle)
  • Low Coupling (Package Import/Export)
  • Versioning per bundle ( [1.0,2,0) )
  • Service Registry

2014-­‑10-­‑23 8

slide-9
SLIDE 9

What is Karaf

  • Container
  • OSGi Applications
  • Ligthtweight
  • expandable to Full Enterprise support
  • Covers all major needs
  • Logging
  • Deployment
  • Configuration

2014-­‑10-­‑23 9

slide-10
SLIDE 10

Karaf - Overview

2014-­‑10-­‑23 10

Console Admin OSGi Framework - Felix / Equinox Logging Deployer Config JMX SSH Blueprint

slide-11
SLIDE 11

Enterprise requirements on Karaf

slide-12
SLIDE 12

Karaf

2014-­‑10-­‑23 12

Servlet 3 JSF 2 JSP JPA 2 JTA CDI EJB 3.1 Bean Validation JAX-WS JAX-RS JAXR JAXB JMS JAAS JASPIC JACC JSR-88 JCA JavaMail JSR-77 RMI JNDI JAX-RPC SAAJ

slide-13
SLIDE 13

Enterprise - Pax Web

2014-­‑10-­‑23 13

Servlet 3 JSF 2 JSP JPA 2 JTA CDI EJB 3.1 Bean Validation JAX-WS JAX-RS JAXR JAXB JMS JAAS JASPIC JACC JSR-88 JCA JavaMail JSR-77 RMI JNDI JAX-RPC SAAJ

slide-14
SLIDE 14

Enterprise - Pax CDI

2014-­‑10-­‑23 14

Servlet 3 JSF 2 JSP JPA 2 JTA CDI EJB 3.1 Bean Validation JAX-WS JAX-RS JAXR JAXB JMS JAAS JASPIC JACC JSR-88 JCA JavaMail JSR-77 RMI JNDI JAX-RPC SAAJ

slide-15
SLIDE 15

Enterprise - Aries

2014-­‑10-­‑23 15

Servlet 3 JSF 2 JSP JPA 2 JTA CDI EJB 3.1 Bean Validation JAX-WS JAX-RS JAXR JAXB JMS JAAS JASPIC JACC JSR-88 JCA JavaMail JSR-77 RMI JNDI JAX-RPC SAAJ

slide-16
SLIDE 16

Enterprise - Tomee aka OpenEJB

2014-­‑10-­‑23 16

Servlet 3 JSF 2 JSP JPA 2 JTA CDI EJB 3.1 Bean Validation JAX-WS JAX-RPC JAX-RS JAXR JAXB JMS JAAS JASPIC JACC JSR-88 JCA JavaMail JSR-77 RMI JNDI SAAJ

slide-17
SLIDE 17

Enterprise - CXF

2014-­‑10-­‑23 17

Servlet 3 JSF 2 JSP JPA 2 JTA CDI EJB 3.1 Bean Validation JAX-WS JAX-RPC JAX-RS JAXR JAXB JMS JAAS JASPIC JACC JSR-88 JCA JavaMail JSR-77 RMI JNDI SAAJ

slide-18
SLIDE 18

Enterprise - ActiveMQ

2014-­‑10-­‑23 18

Servlet 3 JSF 2 JSP JPA 2 JTA CDI EJB 3.1 Bean Validation JAX-WS JAX-RPC JAX-RS JAXR JAXB JMS JAAS JASPIC JACC JSR-88 JCA JavaMail JSR-77 RMI JNDI SAAJ

slide-19
SLIDE 19

Enterprise - Cellar

2014-­‑10-­‑23 19

Servlet 3 JSF 2 JSP JPA 2 JTA CDI EJB 3.1 Bean Validation JAX-WS JAX-RPC JAX-RS JAXR JAXB JMS JAAS JASPIC JACC JSR-88 JCA JavaMail JSR-77 RMI JNDI SAAJ

slide-20
SLIDE 20

Enterprise - Karaf with features

2014-­‑10-­‑23 20

Servlet 3 JSF 2 JSP JPA 2 JTA CDI EJB 3.1 Bean Validation JAX-WS JAX-RPC JAX-RS JAXR SAAJ JAXB JMS JAAS JASPIC JACC JSR-88 JCA JavaMail JSR-77 RMI JNDI

slide-21
SLIDE 21

Specialties

slide-22
SLIDE 22

JPA - Karaf

2014-­‑10-­‑23 22

<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="cookbook" transaction-type="JTA">
 <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
 <jta-data-source>

  • sgi:service/javax.sql.DataSource/(osgi.jndi.service.name=jdbc/cookbook)

</jta-data-source>
 <class>de.nierbeck.apachecon.persistence.entity.Book</class>
 <class>de.nierbeck.apachecon.persistence.entity.Recipe</class> <exclude-unlisted-classes>true</exclude-unlisted-classes>
 <properties>
 <property name="openjpa.Log" value="slf4j" />
 <property name="openjpa.RuntimeUnenhancedClasses" value="supported" />
 <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema"/>
 </properties>
 </persistence-unit>
 </persistence>

slide-23
SLIDE 23

JPA - Karaf

2014-­‑10-­‑23 22

<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="cookbook" transaction-type="JTA">
 <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
 <jta-data-source>

  • sgi:service/javax.sql.DataSource/(osgi.jndi.service.name=jdbc/cookbook)

</jta-data-source>
 <class>de.nierbeck.apachecon.persistence.entity.Book</class>
 <class>de.nierbeck.apachecon.persistence.entity.Recipe</class> <exclude-unlisted-classes>true</exclude-unlisted-classes>
 <properties>
 <property name="openjpa.Log" value="slf4j" />
 <property name="openjpa.RuntimeUnenhancedClasses" value="supported" />
 <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema"/>
 </properties>
 </persistence-unit>
 </persistence>

To have this blueprint JNDI is needed

slide-24
SLIDE 24

JTA - Karaf

2014-­‑10-­‑23 23

<blueprint default-activation=„eager" xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jpa="http://aries.apache.org/xmlns/jpa/v1.0.0" xmlns:tx="http://aries.apache.org/xmlns/transactions/v1.0.0" xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> <bean id="cookBookServiceImpl" class="de.nierbeck.apachecon.persistence.dao.CookBookServiceImpl"> <jpa:context property="em" unitname="cookbook" /> <tx:transaction method="*" value="Required" /> </bean> <service id="cookBookService" ref="cookBookServiceImpl" interface="de.nierbeck.apachecon.persistence.api.CookBookService" /> </blueprint>

slide-25
SLIDE 25

JTA - Karaf

2014-­‑10-­‑23 23

<blueprint default-activation=„eager" xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jpa="http://aries.apache.org/xmlns/jpa/v1.0.0" xmlns:tx="http://aries.apache.org/xmlns/transactions/v1.0.0" xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> <bean id="cookBookServiceImpl" class="de.nierbeck.apachecon.persistence.dao.CookBookServiceImpl"> <jpa:context property="em" unitname="cookbook" /> <tx:transaction method="*" value="Required" /> </bean> <service id="cookBookService" ref="cookBookServiceImpl" interface="de.nierbeck.apachecon.persistence.api.CookBookService" /> </blueprint> To have this blueprint JPA and JTA is needed

slide-26
SLIDE 26

Client - Karaf

2014-­‑10-­‑23 24

<?xml version="1.0" encoding="UTF-8"?> <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" default-activation="lazy"> <reference id="cookBookService" interface="de.nierbeck.apachecon.persistence.api.CookBookService" /> <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0"> <command> <action class="de.nierbeck.apachecon.commands.CreateBook"> <property name="bookService" ref="cookBookService" /> </action> </command> ... </command-bundle> </blueprint>

slide-27
SLIDE 27

Demo

slide-28
SLIDE 28

Persistence

2014-­‑10-­‑23 26

slide-29
SLIDE 29

Client

2014-­‑10-­‑23 27

slide-30
SLIDE 30

Client Shell

2014-­‑10-­‑23 28

slide-31
SLIDE 31

Client - Shell

2014-­‑10-­‑23 29

slide-32
SLIDE 32

Client Shell

2014-­‑10-­‑23 30

slide-33
SLIDE 33

Client - Shell

2014-­‑10-­‑23 31

slide-34
SLIDE 34

Http Service with …

slide-35
SLIDE 35

HTTP Service

2014-­‑10-­‑23 33

  • Using an Activator:

final HttpContext httpContext = httpService .createDefaultHttpContext(); // register the BookServlet // first wait for the DAO-Service CookBookService cookBookService; ServiceReference<CookBookService> serviceReference = bundleContext .getServiceReference(CookBookService.class); cookBookService = bundleContext.getService(serviceReference); //now create the servlet ViewBookServlet viewBookServlet = new ViewBookServlet(); //set the DAO to the Servlet viewBookServlet.setCookBookService(cookBookService); final Dictionary<String, Object> initParams = new Hashtable<String, Object>(); try { httpService.registerServlet("/book", // alias viewBookServlet, initParams, httpContext);

slide-36
SLIDE 36

Whiteboard

2014-­‑10-­‑23 34

  • Using the whiteboard approach via Activator

public void start(BundleContext bc) throws Exception { bundleContext = bc; // first wait for the DAO-Service CookBookService cookBookService; ServiceReference<CookBookService> serviceReference = bundleContext .getServiceReference(CookBookService.class); cookBookService = bundleContext.getService(serviceReference); // create new Servlet ViewBookServlet cookBookViewServlet = new ViewBookServlet(); cookBookViewServlet.setCookBookService(cookBookService); registerServiced = bundleContext.registerService(Servlet.class, cookBookViewServlet, null); }

slide-37
SLIDE 37

Whiteboard

2014-­‑10-­‑23 35

  • Using the whiteboard approach via Blueprint

<blueprint default-activation="eager"> <reference id="cookBookService" interface="de.nierbeck.apachecon.persistence.api.CookBookService" /> <bean id="viewBookServlet" class="de.nierbeck.apachecon.view.ViewBookServlet" > <property name="cookBookService" ref="cookBookService"/> </bean> <service id="servletService" interface="javax.servlet.Servlet" ref="viewBookServlet" /> </blueprint>

slide-38
SLIDE 38

Servlet 3.0 - Just annotation

2014-­‑10-­‑23 36

@WebServlet(urlPatterns = "/book") public class ViewBookServlet extends HttpServlet { /** * */ private static final long serialVersionUID = 1L; @Inject @OsgiService CookBookService cookBookService; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ... } }

slide-39
SLIDE 39

LOST?

slide-40
SLIDE 40

Registering - Servlet

2014-­‑10-­‑23 38

Pax-Web 
 HTTP Service Service- Registry Servlet

slide-41
SLIDE 41

Registering - Servlet

2014-­‑10-­‑23 38

Pax-Web 
 HTTP Service Service- Registry Servlet Registerd

slide-42
SLIDE 42

Registering - Servlet

2014-­‑10-­‑23 38

Pax-Web 
 HTTP Service Service- Registry Servlet Registerd Registerd

slide-43
SLIDE 43

Registering - Whiteboard

2014-­‑10-­‑23 39

Pax-Web 
 WebContainer Service-Tracker Service- Registry Servlet

slide-44
SLIDE 44

Registering - Whiteboard

2014-­‑10-­‑23 39

Pax-Web 
 WebContainer Service-Tracker Service- Registry Servlet Registerd

slide-45
SLIDE 45

Registering - Whiteboard

2014-­‑10-­‑23 39

Pax-Web 
 WebContainer Service-Tracker Service- Registry Servlet Registerd Registerd

slide-46
SLIDE 46

Registering - Whiteboard

2014-­‑10-­‑23 39

Pax-Web 
 WebContainer Service-Tracker Service- Registry Servlet Registerd Registerd

slide-47
SLIDE 47

Registering - WAR

2014-­‑10-­‑23 40

Pax-Web WebContainer Pax-Web 
 WAR Extender Service- Registry WAB-Bundle Servlet

slide-48
SLIDE 48

Registering - WAR

2014-­‑10-­‑23 40

Pax-Web WebContainer Pax-Web 
 WAR Extender Service- Registry WAB-Bundle Servlet Registerd

slide-49
SLIDE 49

Registering - WAR

2014-­‑10-­‑23 40

Pax-Web WebContainer Pax-Web 
 WAR Extender Service- Registry WAB-Bundle Servlet Registerd Registerd

slide-50
SLIDE 50

Registering - WAR

2014-­‑10-­‑23 40

Pax-Web WebContainer Pax-Web 
 WAR Extender Service- Registry WAB-Bundle Servlet Registerd Registerd

slide-51
SLIDE 51

Servlet + JPA / Service

2014-­‑10-­‑23 41

Blueprint 
 Extender Pax-Web 
 WAR Extender JPA-Bundle Service- Registry JPA - Service WEB-Bundle Servlet

slide-52
SLIDE 52

Servlet + JPA / Service

2014-­‑10-­‑23 41

Blueprint 
 Extender Pax-Web 
 WAR Extender JPA-Bundle Service- Registry JPA - Service WEB-Bundle Servlet Registerd

slide-53
SLIDE 53

Servlet + JPA / Service

2014-­‑10-­‑23 41

Blueprint 
 Extender Pax-Web 
 WAR Extender JPA-Bundle Service- Registry JPA - Service WEB-Bundle Servlet Registerd Injected

slide-54
SLIDE 54

Servlet + JPA / Service

2014-­‑10-­‑23 41

Blueprint 
 Extender Pax-Web 
 WAR Extender JPA-Bundle Service- Registry JPA - Service WEB-Bundle Servlet Registerd Registerd Injected

slide-55
SLIDE 55

Demo

slide-56
SLIDE 56

View

2014-­‑10-­‑23 43

slide-57
SLIDE 57

View

2014-­‑10-­‑23 44

slide-58
SLIDE 58

Cluster provided by Apache Karaf Cellar

slide-59
SLIDE 59

Cellar - Cluster Communication

2014-­‑10-­‑23 46

slide-60
SLIDE 60

Cellar - Cluster Communication

2014-­‑10-­‑23 47

Hazelcast

slide-61
SLIDE 61

Cellar - Events

2014-­‑10-­‑23 48

slide-62
SLIDE 62

Cellar - Distributing Bundles

2014-­‑10-­‑23 49

Node A Node B Node C Maven Repository

Hazelcast

slide-63
SLIDE 63

Cellar - Distributing Bundles

2014-­‑10-­‑23 49

Node A Node B Node C Maven Repository

  • sgi:install mvn:groupId/artifactId/version

Hazelcast

slide-64
SLIDE 64

Cellar - Distributing Bundles

2014-­‑10-­‑23 49

Node A Node B Node C Maven Repository

Hazelcast

slide-65
SLIDE 65

Cellar - Distributing Bundles

2014-­‑10-­‑23 49

Node A Node B Node C Maven Repository

Hazelcast

slide-66
SLIDE 66

Cellar - Distributing Bundles

2014-­‑10-­‑23 49

Node A Node B Node C Maven Repository

Hazelcast

slide-67
SLIDE 67

Cellar - Distributing Bundles

2014-­‑10-­‑23 49

Node A Node B Node C Maven Repository

Hazelcast

slide-68
SLIDE 68

Cellar - Distributing Bundles

2014-­‑10-­‑23 49

Node A Node B Node C Maven Repository

Hazelcast

slide-69
SLIDE 69

Cellar - Distributing Bundles

2014-­‑10-­‑23 49

Node A Node B Node C Maven Repository

Hazelcast

slide-70
SLIDE 70

Cellar - Distributing Bundles

2014-­‑10-­‑23 49

Node A Node B Node C Maven Repository

Hazelcast

DEPRECATED

slide-71
SLIDE 71

Cellar - Distributing Bundles

2014-­‑10-­‑23 49

Node A Node B Node C Maven Repository

Hazelcast

DEPRECATED

cluster:install mvn:groupId/artifactId/version

slide-72
SLIDE 72

Cellar - RMI

2014-­‑10-­‑23 50

Group 1 Node A Consumes OSGi-Service Group 2 Node B Consumes OSGi-Service Node C Consumes OSGi-Service Node A Provides OSGi-Service Node B Provides OSGi-Service

Hazelcast

slide-73
SLIDE 73

Cellar - Web session failover

2014-­‑10-­‑23 51

Node A

Hazelcast

DataBase Client Servlet Filter Node B Servlet Filter

slide-74
SLIDE 74

Cellar - Web session failover

2014-­‑10-­‑23 51

Node A

Hazelcast

DataBase Client Servlet Filter Node B Servlet Filter

slide-75
SLIDE 75

Cellar - Web session failover

2014-­‑10-­‑23 51

Node A

Hazelcast

DataBase Client Servlet Filter Node B Servlet Filter

slide-76
SLIDE 76

Cellar - Web session failover

2014-­‑10-­‑23 51

Node A

Hazelcast

DataBase Client Servlet Filter Node B Servlet Filter

slide-77
SLIDE 77

Cellar - Web session failover

2014-­‑10-­‑23 51

Node A

Hazelcast

DataBase Client Servlet Filter Node B Servlet Filter

slide-78
SLIDE 78

Cellar - Web session failover

2014-­‑10-­‑23 51

Node A

Hazelcast

DataBase Client Servlet Filter Node B Servlet Filter

slide-79
SLIDE 79

Cellar - Web session failover

2014-­‑10-­‑23 51

Node A

Hazelcast

DataBase Client Servlet Filter Node B Servlet Filter

slide-80
SLIDE 80

Cellar - Web session failover

2014-­‑10-­‑23 51

Node A

Hazelcast

DataBase Client Servlet Filter Node B Servlet Filter

slide-81
SLIDE 81

Cellar - Web session failover

2014-­‑10-­‑23 51

Node A

Hazelcast

DataBase Client Servlet Filter Node B Servlet Filter

slide-82
SLIDE 82

Cellar - Web session failover

2014-­‑10-­‑23 51

Node A

Hazelcast

DataBase Client Servlet Filter Node B Servlet Filter

slide-83
SLIDE 83

Cellar - Web session failover

2014-­‑10-­‑23 51

Node A

Hazelcast

DataBase Client Servlet Filter Node B Servlet Filter

slide-84
SLIDE 84

Cellar - Web session failover

2014-­‑10-­‑23 51

Node A

Hazelcast

DataBase Client Servlet Filter Node B Servlet Filter

slide-85
SLIDE 85

Cellar - Web session failover

2014-­‑10-­‑23 51

Node A

Hazelcast

DataBase Client Servlet Filter Node B Servlet Filter

slide-86
SLIDE 86

Cluster - Demo

slide-87
SLIDE 87

Presentation Layer

2014-­‑10-­‑23 53

slide-88
SLIDE 88

web.xml - Hazelcast

2014-­‑10-­‑23 54

  • Hazelcast for Session Replication

<?xml version="1.0" encoding="UTF-8"?> <web-app 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" version="3.0"> <filter> <filter-name>hazelcast-filter</filter-name> <filter-class>com.hazelcast.web.WebFilter</filter-class> <!-- Name of the distributed map storing your web session objects

  • ->

<init-param> <param-name>map-name</param-name> <param-value>my-sessions</param-value> </init-param> <init-param> <param-name>sticky-session</param-name> <param-value>false</param-value> </init-param> </filter> <filter-mapping> <filter-name>hazelcast-filter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> <dispatcher>REQUEST</dispatcher> </filter-mapping> <listener> <listener-class>com.hazelcast.web.SessionListener</listener-class> </listener> </web-app>

slide-89
SLIDE 89

View

2014-­‑10-­‑23 55

slide-90
SLIDE 90

View

2014-­‑10-­‑23 56

slide-91
SLIDE 91

View

2014-­‑10-­‑23 57

slide-92
SLIDE 92

SUMMARY

slide-93
SLIDE 93

Enterprise - Karaf

2014-­‑10-­‑23 59

Servlet 3 JSF 2 JSP JPA 2 JTA CDI EJB 3.1 JAX-WS JAX-RPC JAX-RS JAXR SAAJ JAXB JMS JAAS RMI JNDI

slide-94
SLIDE 94

JEE with Karaf?

  • Adoptions needed? YES
  • Minor on Persistence - JNDI lookup
  • Minor on transaction - Blueprint JTA
  • Wiring of Services:
  • Use Blueprint
  • Use Servlet 3.0 with CDI - @OsgiService
  • Session Replication throughout cluster, it’s still standard

Hazelcast

2014-­‑10-­‑23 60

slide-95
SLIDE 95

Resources

  • @anierbeck
  • notitzblog.nierbeck.de
  • https://github.com/ANierbeck/karaf-enterprise-sample
  • www.codecentric.de
  • karaf.apache.org
  • https://ops4j1.jira.com/wiki/display/paxweb/Pax+Web
  • #karaf at irc.codehaus.org
  • https://www.packtpub.com/application-development/apache-karaf-cookbook
  • Pictures, mainly from flickr

2014-­‑10-­‑23 61

slide-96
SLIDE 96
slide-97
SLIDE 97

THANKS FOR LISTENING

slide-98
SLIDE 98

Thanks to the Apache Community

slide-99
SLIDE 99

Questions

slide-100
SLIDE 100

Thanks