APACHE DELTASPIKE
THE CDITOOLBOX
@antoine_sd
ANTOINE SABOT-DURAND
• Senior Software Engineer @Red Hat
• Java & OSS :
• CDI co-spec lead
• CDI community development
• Apache Deltaspike committer
• @antoine_sd
AGENDA
• What is Apache Deltaspike?
• Deltaspike Core
• Deltaspike Modules
• Conclusion
WHAT IS APACHE DELTASPIKE
CDI & DELTASPIKE
• CDI is a specification. It doesn’t provide business features
• but it includes a powerful hook to add these business features
• The “portable extensions” feature is this hook
• Thanks to it, CDI can be easily enhanced with new high level features
APACHE DELTASPIKE IS…
• A collection of ready to use extensions to help you in your projects
• A toolbox to help you develop new CDI portable extensions
• A great way to learn how to develop your own extension by
browsing the source code
• The most obvious entry point to CDI eco-system
WHERE DOES IT COMES FROM?
Font: Avenir Light
Font-size: 64pt
Letter-spacing: 410
RGB: 51,181 229
HEX: #35b4e3
C=66.45 M=8.61 Y=1.97 K=0
Miscellaneous CDI Initiatives
TESTED WITH
• CDI 1.0, 1.1, 1.2
• JBoss Weld 1.1.3 to 2.2.8
• OpenWebBeans 1.1.1 to 1.2.7
• JBoss AS 7.x,WildFly 8.x
• JBoss EAP 6.x
• TomEE 1.0.x - 1.7.x
• GlassFish 3.x, 4.x
• Weblogic 12c
A BIT OF HISTORY
Dec 2011 Feb 2012 May 2013 June 2014
ProjectLaunch
rel.0.1
rel.0.4(outofincubator)
rel.1.0
Dec 2014
rel.1.2.1
WHAT’S INCLUDED?
Apache Deltaspike is organized in the following modules
Container control provides a portable way to boot CDI container
Core Module core features and helpers. Used by all other modules below
Partial Bean Module develop generic handler to choose code dynamically at runtime
Scheduler Module add job scheduling with Quartz or any other scheduler
Security Module add security checking. Integration of 3rd party security framework
BeanValidation Module CDI integration for BeanValidation 1.0
JPA Module Enhance JPA integration for CDI 1.0. Mostly useless in Java EE 7
Data Module Implements repository pattern removing JPA boilerplate code
Servlet Module Enhance Servlet integration for CDI 1.0. Mostly useless in Java EE 7
JSF Module Enhance JSF by adding CDI scopes, typesafe view config, etc…
Test control provide a test solution for CDI based on Junit
MODULES AND DEPENDENCIES
Partial Bean Core
Bean
Validation
JPAData
Security
JSF
Scheduler Servlet
Test CTRL
Containers
CTRL
ADDING DELTASPIKETOYOUR POM.XML
<dependency>

<groupId>org.apache.deltaspike.core</groupId>

<artifactId>deltaspike-core-api</artifactId>

<version>1.2.1</version>

<scope>compile</scope>

</dependency>



<dependency>

<groupId>org.apache.deltaspike.core</groupId>

<artifactId>deltaspike-core-impl</artifactId>

<version>1.2.1</version>

<scope>runtime</scope>

</dependency>
DELTASPIKE CORE
CONFIGURATION 1/2
• DeltaSpike provides a powerful configuration API / SPI
• It doesn’t depend on CDI, thus it can be used in portable extension
• The entry point is the ConfigResolver class
• ConfigSource SPI allows to add new configuration source
• Each config has a priority (ordinal).This highest is picked first
CONFIGURATION 2/2
Out of the Box Config Sources
ConfigSource Priority Notes
System properties 400
Environment properties 300
JNDI values 200 java:comp/env/deltaspike
Properties files value 100 META-INF/apache-deltaspike.properties
CONFIGURATION USAGE
//ConfigResolver can be used directly without CDI dependency (useful in extensions)

String dbUserName = ConfigResolver.getPropertyValue("databaseconfig.username");
…
//Config can also be used in CDI mode and typeSafe config

@Inject

@ConfigProperty(name = "endpoint.poll.interval")

private Integer p; // DS provides conversion for String, Integer, Long, Boolean, Float
…
//But you can provide your own ConfigProperty producer to perform custom conversion

@ApplicationScoped

public class MyConfigPropertyProducer extends BaseConfigPropertyProducer {

@Produces @ConfigProperty(name = "ignored")

public MyType produceStringConfiguration(InjectionPoint injectionPoint) {
String strValue = getStringPropertyValue(injectionPoint);
…
}

}
PROJECT STAGES
• Allows to use implementations depending on current environment
• You can defined your owned stage or used the provided ones
• Pre-defined project stages:
• UnitTest, Development, SystemTest, IntegrationTest, Staging, Production
• Project Stage is configured thru DS configuration mechanism
PROJECT STAGE EXAMPLE
//Setting project stage with environment property
-Dorg.apache.deltaspike.ProjectStage=Development
…
//Using project stage

@Inject

private ProjectStage projectStage;

boolean isDevProjectStage = ProjectStage.Development.equals(this.projectStage);
BEAN EXCLUSION WITH @EXCLUDE
@Exclude //like CDI 1.1+ @Vetoed but limited to a class
@Exclude(ifProjectStage=Production.class) //based on project stage


@Exclude(exceptIfProjectStage=UnitTest.class) //based on project stage


@Exclude(onExpression="myProperty==myValue") //based on config value


@Exclude(onExpression="[cust exp]", interpretedBy=CustomExpInterpreter.class) //custom
EXCEPTION HANDLERS
• Based on CDI event
• ExceptionToCatchEvent class sends the exception to DS
• @ExceptionHandler marks a class as handlers container
• @Handles and ExceptionEvent<T> handle an exception
EXCEPTION HANDLER EXAMPLE
public class InventoryActions {

@PersistenceContext

private EntityManager em;

@Inject

private Event<ExceptionToCatchEvent> catchEvent;



public Integer queryForItem(Item i) {

try {

Query q = em.createQuery("SELECT i from Item i where i.id = :id");

q.setParameter("id", item.getId());

return q.getSingleResult();

} catch (PersistenceException e) {

catchEvent.fire(new ExceptionToCatchEvent(e));

}

}

}
…
@ExceptionHandler

public class MyHandler {

void handleTheException(@Handles ExceptionEvent<Throwable> exEvent) {

// Do anything with the exception

exEvent.handleAndContinue();

}

}
INJECTABLE RESOURCE
@Inject

@InjectableResource(location = "/version.txt")

private InputStream is; //Can be customised for alternate sources



public String getVersion() throws IOException {

try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {

return br.readLine();

}

}
INTERNATIONALISATION (I18N)
package org.apache.deltaspike.example



@MessageBundle // Can only be applied on an interface

public interface SimpleMessage
// Will map the org/apache/deltaspike/example/SimpleMessage bundle

{

@MessageTemplate(“{my_message}”) // Will map my_message key in bundle

String welcomeToDeltaSpike();
// For value with parameter i.e welcome_to = Welcome to %s 

@MessageTemplate("{welcome_to}")

String welcomeTo(String name);


}
CDI METADATA BUILDERS
• Creating CDI SPI metadata for you extension can be cumbersome
• Deltaspike provides builder to ease the work and reduce code verbosity
• Major builder are
• AnnotatedTypeBuilder
• BeanBuilder
• WrapperBeanBuilder
BUILDING META DATA EXAMPLES
void addTimedBinding(@Observes BeforeBeanDiscovery bbd) {

AnnotationLiteral<Nonbinding> nonbindingLiteral = new AnnotationLiteral<Nonbinding>(){};

AnnotatedTypeBuilder<Timed> atb = new AnnotatedTypeBuilder<Timed>()

.readFromType(Timed.class)

.addToMethod(Timed.class.getMethod("name"), nonbindingLiteral)

.addToMethod(Timed.class.getMethod(“absolute"),nonbindingLiteral);

bbd.addInterceptorBinding(atb.create());

}
…
public void registerGenericBeans(@Observes AfterBeanDiscovery abd) {

BeanBuilder<User> ubb = new BeanBuilder<User>(beanManager)

.readFromType(User.class)

.passivationCapable(true)

.addTypes(otherTypes);

if (weAreOnWeb)

ubb.scope(SessionScoped.class);

else

ubb.scope(ApplicationScoped.class);


abd.addBean(ubb.create());

}
DELTASPIKE MODULES
CONTAINER CONTROL
public class MainApp {

public static void main(String[] args) {



CdiContainer cdiContainer = CdiContainerLoader.getCdiContainer();

cdiContainer.boot();



// Starting the application-context enables use of @ApplicationScoped beans

ContextControl contextControl = cdiContainer.getContextControl();

contextControl.startContext(ApplicationScoped.class);



// You can use CDI here



cdiContainer.shutdown();

}

}
TEST CONTROL EXAMPLES
@RunWith(CdiTestRunner.class)

public class MyCdiTest {

@Inject

private MyBean bean;

}

…

@RunWith(CdiTestSuiteRunner.class)

@Suite.SuiteClasses({ TestX.class, TestY.class})

public class SuiteLevelContainerControl{}

…

@RunWith(CdiTestRunner.class)

@TestControl(projectStage = CustomTestStage.class)

public class TestStageControl {

@Test

@TestControl(projectStage = ProjectStage.Development.class)

public void checkDevEnv(){}

}
SECURITY
@Retention(value = RetentionPolicy.RUNTIME)

@Target({ ElementType.TYPE, ElementType.METHOD })

@Documented

@SecurityBindingType

public @interface AdminOnly {}
…
@ApplicationScoped

public class ApplicationAuthorizer {

@Secures

@AdminOnly // Binding security to permission verifier

public boolean verifyPermission(InvocationContext invocationContext,

BeanManager manager, @Logged User user) throws Exception {

return user.getRole().equalsIgnoreCase("Admin");

}

}
…
@AdminOnly

public void startAdministrativeTask() {

// Only admins can start admin tasks

}
SCHEDULER
@Scheduled(cronExpression = "0 0/10 * * * ?")

public class CdiAwareQuartzJob implements org.quartz.Job

{

@Inject

private MyService service;



@Override

public void execute(JobExecutionContext context) throws JobExecutionException

{

//...

}

}
DATA MODULE
DATA MODULE
• Data module is an implementation of the repository pattern
• At the moment it only support RDBMS thru JPA
• But it could be extended to support other data services
• It uses the “partial bean” module to dynamically create
implementation at runtime
-Eric Evans (in Domain Driven Design)
« A Repository represents all objects of a certain
type as a conceptual set. It acts like a collection,
except with more elaborate querying capability.»
REPOSITORY PATTERN DEFINITION
SIMPLE EXAMPLE
@Repository //Repo definition to put an interface

public interface UserRepository extends EntityRepository<User, Long> {



// method signature creates the JPQL with the partial bean mechanism

public User findByUsernameAndPassword(String username, char[] password);



}

…

@Repository

public interface PostRepostiory extends EntityRepository<Post, Long> {





@Query("SELECT p FROM Post AS p WHERE p.author in (?1)")

public List<Post> findByFollowing(List<User> following);



}
JPA FUNCTIONS SUPPORTED
• count();
• findAll();
• findBy(PK);
• flush();
• refresh();
• remove();
• save();
• saveAndFlush();
CONCLUSION
• More info & doc on http://deltaspike.apache.org
• Follow @Deltaspiketeam onTwitter
• Visit examples: https://deltaspike.apache.org/external.html
• & http://jboss.org/developer-materials/#!keyword=Deltaspike
• Questions ?

Apache DeltaSpike the CDI toolbox

  • 1.
  • 2.
    ANTOINE SABOT-DURAND • SeniorSoftware Engineer @Red Hat • Java & OSS : • CDI co-spec lead • CDI community development • Apache Deltaspike committer • @antoine_sd
  • 3.
    AGENDA • What isApache Deltaspike? • Deltaspike Core • Deltaspike Modules • Conclusion
  • 4.
    WHAT IS APACHEDELTASPIKE
  • 5.
    CDI & DELTASPIKE •CDI is a specification. It doesn’t provide business features • but it includes a powerful hook to add these business features • The “portable extensions” feature is this hook • Thanks to it, CDI can be easily enhanced with new high level features
  • 6.
    APACHE DELTASPIKE IS… •A collection of ready to use extensions to help you in your projects • A toolbox to help you develop new CDI portable extensions • A great way to learn how to develop your own extension by browsing the source code • The most obvious entry point to CDI eco-system
  • 7.
    WHERE DOES ITCOMES FROM? Font: Avenir Light Font-size: 64pt Letter-spacing: 410 RGB: 51,181 229 HEX: #35b4e3 C=66.45 M=8.61 Y=1.97 K=0 Miscellaneous CDI Initiatives
  • 8.
    TESTED WITH • CDI1.0, 1.1, 1.2 • JBoss Weld 1.1.3 to 2.2.8 • OpenWebBeans 1.1.1 to 1.2.7 • JBoss AS 7.x,WildFly 8.x • JBoss EAP 6.x • TomEE 1.0.x - 1.7.x • GlassFish 3.x, 4.x • Weblogic 12c
  • 9.
    A BIT OFHISTORY Dec 2011 Feb 2012 May 2013 June 2014 ProjectLaunch rel.0.1 rel.0.4(outofincubator) rel.1.0 Dec 2014 rel.1.2.1
  • 10.
    WHAT’S INCLUDED? Apache Deltaspikeis organized in the following modules Container control provides a portable way to boot CDI container Core Module core features and helpers. Used by all other modules below Partial Bean Module develop generic handler to choose code dynamically at runtime Scheduler Module add job scheduling with Quartz or any other scheduler Security Module add security checking. Integration of 3rd party security framework BeanValidation Module CDI integration for BeanValidation 1.0 JPA Module Enhance JPA integration for CDI 1.0. Mostly useless in Java EE 7 Data Module Implements repository pattern removing JPA boilerplate code Servlet Module Enhance Servlet integration for CDI 1.0. Mostly useless in Java EE 7 JSF Module Enhance JSF by adding CDI scopes, typesafe view config, etc… Test control provide a test solution for CDI based on Junit
  • 11.
    MODULES AND DEPENDENCIES PartialBean Core Bean Validation JPAData Security JSF Scheduler Servlet Test CTRL Containers CTRL
  • 12.
  • 13.
  • 14.
    CONFIGURATION 1/2 • DeltaSpikeprovides a powerful configuration API / SPI • It doesn’t depend on CDI, thus it can be used in portable extension • The entry point is the ConfigResolver class • ConfigSource SPI allows to add new configuration source • Each config has a priority (ordinal).This highest is picked first
  • 15.
    CONFIGURATION 2/2 Out ofthe Box Config Sources ConfigSource Priority Notes System properties 400 Environment properties 300 JNDI values 200 java:comp/env/deltaspike Properties files value 100 META-INF/apache-deltaspike.properties
  • 16.
    CONFIGURATION USAGE //ConfigResolver canbe used directly without CDI dependency (useful in extensions)
 String dbUserName = ConfigResolver.getPropertyValue("databaseconfig.username"); … //Config can also be used in CDI mode and typeSafe config
 @Inject
 @ConfigProperty(name = "endpoint.poll.interval")
 private Integer p; // DS provides conversion for String, Integer, Long, Boolean, Float … //But you can provide your own ConfigProperty producer to perform custom conversion
 @ApplicationScoped
 public class MyConfigPropertyProducer extends BaseConfigPropertyProducer {
 @Produces @ConfigProperty(name = "ignored")
 public MyType produceStringConfiguration(InjectionPoint injectionPoint) { String strValue = getStringPropertyValue(injectionPoint); … }
 }
  • 17.
    PROJECT STAGES • Allowsto use implementations depending on current environment • You can defined your owned stage or used the provided ones • Pre-defined project stages: • UnitTest, Development, SystemTest, IntegrationTest, Staging, Production • Project Stage is configured thru DS configuration mechanism
  • 18.
    PROJECT STAGE EXAMPLE //Settingproject stage with environment property -Dorg.apache.deltaspike.ProjectStage=Development … //Using project stage
 @Inject
 private ProjectStage projectStage;
 boolean isDevProjectStage = ProjectStage.Development.equals(this.projectStage);
  • 19.
    BEAN EXCLUSION WITH@EXCLUDE @Exclude //like CDI 1.1+ @Vetoed but limited to a class @Exclude(ifProjectStage=Production.class) //based on project stage 
 @Exclude(exceptIfProjectStage=UnitTest.class) //based on project stage 
 @Exclude(onExpression="myProperty==myValue") //based on config value 
 @Exclude(onExpression="[cust exp]", interpretedBy=CustomExpInterpreter.class) //custom
  • 20.
    EXCEPTION HANDLERS • Basedon CDI event • ExceptionToCatchEvent class sends the exception to DS • @ExceptionHandler marks a class as handlers container • @Handles and ExceptionEvent<T> handle an exception
  • 21.
    EXCEPTION HANDLER EXAMPLE publicclass InventoryActions {
 @PersistenceContext
 private EntityManager em;
 @Inject
 private Event<ExceptionToCatchEvent> catchEvent;
 
 public Integer queryForItem(Item i) {
 try {
 Query q = em.createQuery("SELECT i from Item i where i.id = :id");
 q.setParameter("id", item.getId());
 return q.getSingleResult();
 } catch (PersistenceException e) {
 catchEvent.fire(new ExceptionToCatchEvent(e));
 }
 }
 } … @ExceptionHandler
 public class MyHandler {
 void handleTheException(@Handles ExceptionEvent<Throwable> exEvent) {
 // Do anything with the exception
 exEvent.handleAndContinue();
 }
 }
  • 22.
    INJECTABLE RESOURCE @Inject
 @InjectableResource(location ="/version.txt")
 private InputStream is; //Can be customised for alternate sources
 
 public String getVersion() throws IOException {
 try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
 return br.readLine();
 }
 }
  • 23.
    INTERNATIONALISATION (I18N) package org.apache.deltaspike.example
 
 @MessageBundle// Can only be applied on an interface
 public interface SimpleMessage // Will map the org/apache/deltaspike/example/SimpleMessage bundle
 {
 @MessageTemplate(“{my_message}”) // Will map my_message key in bundle
 String welcomeToDeltaSpike(); // For value with parameter i.e welcome_to = Welcome to %s 
 @MessageTemplate("{welcome_to}")
 String welcomeTo(String name); 
 }
  • 24.
    CDI METADATA BUILDERS •Creating CDI SPI metadata for you extension can be cumbersome • Deltaspike provides builder to ease the work and reduce code verbosity • Major builder are • AnnotatedTypeBuilder • BeanBuilder • WrapperBeanBuilder
  • 25.
    BUILDING META DATAEXAMPLES void addTimedBinding(@Observes BeforeBeanDiscovery bbd) {
 AnnotationLiteral<Nonbinding> nonbindingLiteral = new AnnotationLiteral<Nonbinding>(){};
 AnnotatedTypeBuilder<Timed> atb = new AnnotatedTypeBuilder<Timed>()
 .readFromType(Timed.class)
 .addToMethod(Timed.class.getMethod("name"), nonbindingLiteral)
 .addToMethod(Timed.class.getMethod(“absolute"),nonbindingLiteral);
 bbd.addInterceptorBinding(atb.create());
 } … public void registerGenericBeans(@Observes AfterBeanDiscovery abd) {
 BeanBuilder<User> ubb = new BeanBuilder<User>(beanManager)
 .readFromType(User.class)
 .passivationCapable(true)
 .addTypes(otherTypes);
 if (weAreOnWeb)
 ubb.scope(SessionScoped.class);
 else
 ubb.scope(ApplicationScoped.class); 
 abd.addBean(ubb.create());
 }
  • 26.
  • 27.
    CONTAINER CONTROL public classMainApp {
 public static void main(String[] args) {
 
 CdiContainer cdiContainer = CdiContainerLoader.getCdiContainer();
 cdiContainer.boot();
 
 // Starting the application-context enables use of @ApplicationScoped beans
 ContextControl contextControl = cdiContainer.getContextControl();
 contextControl.startContext(ApplicationScoped.class);
 
 // You can use CDI here
 
 cdiContainer.shutdown();
 }
 }
  • 28.
    TEST CONTROL EXAMPLES @RunWith(CdiTestRunner.class)
 publicclass MyCdiTest {
 @Inject
 private MyBean bean;
 }
 …
 @RunWith(CdiTestSuiteRunner.class)
 @Suite.SuiteClasses({ TestX.class, TestY.class})
 public class SuiteLevelContainerControl{}
 …
 @RunWith(CdiTestRunner.class)
 @TestControl(projectStage = CustomTestStage.class)
 public class TestStageControl {
 @Test
 @TestControl(projectStage = ProjectStage.Development.class)
 public void checkDevEnv(){}
 }
  • 29.
    SECURITY @Retention(value = RetentionPolicy.RUNTIME)
 @Target({ElementType.TYPE, ElementType.METHOD })
 @Documented
 @SecurityBindingType
 public @interface AdminOnly {} … @ApplicationScoped
 public class ApplicationAuthorizer {
 @Secures
 @AdminOnly // Binding security to permission verifier
 public boolean verifyPermission(InvocationContext invocationContext,
 BeanManager manager, @Logged User user) throws Exception {
 return user.getRole().equalsIgnoreCase("Admin");
 }
 } … @AdminOnly
 public void startAdministrativeTask() {
 // Only admins can start admin tasks
 }
  • 30.
    SCHEDULER @Scheduled(cronExpression = "00/10 * * * ?")
 public class CdiAwareQuartzJob implements org.quartz.Job
 {
 @Inject
 private MyService service;
 
 @Override
 public void execute(JobExecutionContext context) throws JobExecutionException
 {
 //...
 }
 }
  • 31.
  • 32.
    DATA MODULE • Datamodule is an implementation of the repository pattern • At the moment it only support RDBMS thru JPA • But it could be extended to support other data services • It uses the “partial bean” module to dynamically create implementation at runtime
  • 33.
    -Eric Evans (inDomain Driven Design) « A Repository represents all objects of a certain type as a conceptual set. It acts like a collection, except with more elaborate querying capability.» REPOSITORY PATTERN DEFINITION
  • 34.
    SIMPLE EXAMPLE @Repository //Repodefinition to put an interface
 public interface UserRepository extends EntityRepository<User, Long> {
 
 // method signature creates the JPQL with the partial bean mechanism
 public User findByUsernameAndPassword(String username, char[] password);
 
 }
 …
 @Repository
 public interface PostRepostiory extends EntityRepository<Post, Long> {
 
 
 @Query("SELECT p FROM Post AS p WHERE p.author in (?1)")
 public List<Post> findByFollowing(List<User> following);
 
 }
  • 35.
    JPA FUNCTIONS SUPPORTED •count(); • findAll(); • findBy(PK); • flush(); • refresh(); • remove(); • save(); • saveAndFlush();
  • 36.
    CONCLUSION • More info& doc on http://deltaspike.apache.org • Follow @Deltaspiketeam onTwitter • Visit examples: https://deltaspike.apache.org/external.html • & http://jboss.org/developer-materials/#!keyword=Deltaspike • Questions ?