CDI portable extensions are one of greatest features of Java EE allowing the platform to be extended in a clean and portable way. But allowing extension is just part of the story. CDI opens the door to a whole new eco-system for Java EE, but it’s not the role of the specification to create these extensions.
Apache DeltaSpike is the project that leads this brand new eco-system by providing useful extension modules for CDI applications as well as tools to ease the creation of new ones.
In this session, we’ll start by presenting the DeltaSpike toolbox and show how it helps you to develop for CDI. Then we’ll describe the major extensions included in DeltaSpike, including 'configuration', 'scheduling' and 'data'.
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 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
8. 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
9. 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
10. 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
14. 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
15. 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
16. 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);
…
}
}
17. 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
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
• 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
21. 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();
}
}
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 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());
}
27. 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();
}
}
28. 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(){}
}
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
}
32. 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
33. -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
34. 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);
}