Tuesday, December 31, 2013

deltaspike in 2013

here a short overview about the progress of deltaspike in 2013:

first of all the project graduated (apache incubator -> apache top-level-project).

multiple modules have been added:

  • bean-validation
  • data
  • partial-bean
  • scheduler
  • servlet
  • test-control

existing modules have been improved (e.g. optional support for jsf 2.2 specific parts).

the documentation has been improved (but there is still room for further improvements).

almost all myfaces-codi features have been ported to deltaspike and most of them have been improved.

two versions have been released and the next one will follow soon.

Monday, December 30, 2013

cdi and spring-mvc

based on http://os890.blogspot.co.at/2013/12/add-on-spring-bridge-with-deltaspike.html it's possible to write e.g. a cdi bridge for spring-mvc. with that it's possible to use cdi-beans as spring-mvc controllers. please notice that it is just a feasibility study.

https://github.com/os890/cdi-spring-mvc-showcase/tree/cdi-managed is the current state of the official demo with cdi-beans as controllers (instead of spring-beans).

[add-on] spring-bridge with deltaspike

cdi and deltaspike are very powerful and in several cases all you need. some might argue that other containers like spring have a richer ecosystem. integrating 3rd party frameworks is usually not a big deal and several even provide a nice api (which doesn't require an additional wrapper or api-layer). however, if there is a good reason why one of the additional spring-projects would be nice to use, it's usually also possible to integrate/use it in a cdi-based application via a cdi-spring bridge. in combination with deltaspike it's easy to implement it.

ds-spring-bridge-addon is one of such two-way bridges. it allows to inject spring-beans into cdi-beans as well as cdi-beans into spring-beans as long as the used concepts (like qualifiers,... are compatible).

per default the bridge will bootstrap the spring-container as soon as it is needed. in case of web-applications, it's possible to use WebappAwareSpringContainerManager (which also delegates to the context-loader of spring). as shown in the tests and examples, it's possible to use it with plain java-se, servlet-containers like tomcat as well as ee-containers like tomee.

Thursday, December 26, 2013

[deltaspike] validate view-config

apache deltaspike provides an improved version of the view-config known from apache myfaces codi. one of many big advantages is the type-safety (even for navigation). the only missing part is the validation against real files and folders. however, if your view-ids correspond with the real file-names (which is good practice anyway), it's easy to do it manually:
public class ViewConfigValidator implements ServletContextListener
{
@Override
public void contextInitialized(ServletContextEvent sce)
{
ViewConfigResolver viewConfigResolver =
BeanProvider.getContextualReference(ViewConfigResolver.class);
for (ConfigDescriptor configDescriptor :
viewConfigResolver.getConfigDescriptors())
{
try
{
if (!isInternal(configDescriptor.getConfigClass()) &&
sce.getServletContext()
.getResource(configDescriptor.getPath()) == null)
{
throw new IllegalStateException("path " +
configDescriptor.getPath() +
" doesn't exist, but it's mapped by " +
configDescriptor.getConfigClass().getName());
}
}
catch (MalformedURLException e)
{
throw ExceptionUtils.throwAsRuntimeException(e);
}
}
}
//needed with deltaspike 0.5
private boolean isInternal(Class configClass)
{
return ViewConfig.class.equals(configClass) ||
DefaultErrorView.class.equals(configClass) ||
ViewRef.class.equals(configClass) ||
ViewRef.Manual.class.equals(configClass);
}
@Override
public void contextDestroyed(ServletContextEvent sce)
{
}
}


in an ee6+ application-server it's possible to annotate this class with @WebListener (-> no further config is needed). in case of a manual cdi-setup (e.g. with tomcat), it's needed to configure the listener after the listener of the cdi-implementation (because cdi needs to be bootstrapped before this listener gets called).

with all versions after v0.5, deltaspike will do this check out-of-the-box.

Monday, December 16, 2013

[add-on] simple quartz integration with deltaspike 0.5

the container-control module provided by deltaspike is very powerful. recently i created a simple cdi integration for junit based on this module. integrating a scheduler like quartz is even easer. therefore i prototyped a very simple (= only cron-expressions are supported) deltaspike scheduler add-on. the default-implementation delegates to quartz, however, it's possible to integrate it with any scheduler (if cron-expressions are supported).

the major use-case is simple. just annotate your job-implementations (in case of quartz: org.quartz.Job) with @Scheduled(cronExpression = "[your expression]") and it will be scheduled/installed automatically at the end of the bootstrapping process.

it's possible to use cdi based injection:


@Scheduled(cronExpression = "0 0/10 * * * ?")
public class CdiAwareQuartzJob implements org.quartz.Job
{
@Inject
private MyService service;
@Override
public void execute(JobExecutionContext context)
throws JobExecutionException
{
//...
}
}


furthermore, the request- and session-scope get started (and stopped) per job-execution. however, it can be controlled via @Scheduled#startScopes and it's possible to provide a description as well as a type-safe job-group.

beyond that it's also possible to inject the scheduler and control (scheduleJob, interruptJob, startJobManually,...) it manually - e.g.:
@ApplicationScoped
public class SchedulerController
{
@Inject
private Scheduler<Job> jobScheduler;
public void onPause(@Observes PauseJobEvent /*custom event*/ jobEvent)
{
//using it with events is optional
this.jobScheduler.pauseJob(jobEvent.getJobClass());
}
public void onResume(@Observes ResumeJobEvent /*custom event*/ jobEvent)
{
//using it with events is optional
this.jobScheduler.resumeJob(jobEvent.getJobClass());
}
}


With 'false' for @Scheduled#onStartup it's even possible to schedule/install jobs dynamically - e.g.:
@ApplicationScoped
public class ProjectStageAwareSchedulerController
{
@Inject
private Scheduler<Job> jobScheduler;
@Inject
private ProjectStage projectStage;
public void registerJobs()
{
if (ProjectStage.Production.equals(this.projectStage))
{
//see 'false' for @Scheduled#onStartup
this.jobScheduler.scheduleJob(ManualCdiAwareQuartzJob.class);
}
}
@Scheduled(cronExpression = "0 0/10 * * * ?", onStartup = false)
public class ManualCdiAwareQuartzJob implements org.quartz.Job
{
@Inject
private MyService service;
@Override
public void execute(JobExecutionContext context)
throws JobExecutionException
{
//...
}
}
}


Update:
This add-on is part of all versions of DeltaSpike after v0.5

Monday, December 2, 2013

[add-on] cdi tests with deltaspike 0.5

arquillian is nice, however, several projects don't need/use it.
several of them implemented a custom approach to control the cdi-container, start/stop scopes and check invalid state (esp. after a failed test). usually the basic tasks are the same or very similar. therefore i prototyped a deltaspike test-ctrl add-on based on some use-cases:

//starts the container once and one session + request per test-method
@RunWith(CdiTestRunner.class)
public class ContainerAndInjectionControl
{
@Inject
private ApplicationScopedBean applicationScopedBean;
@Inject
private SessionScopedBean sessionScopedBean;
@Inject
private RequestScopedBean requestScopedBean;
//test the injected beans
}
//starts the container and session once and one request per test-method
@RunWith(CdiTestRunner.class)
@TestControl(startScopes = SessionScoped.class)
public class CustomizedScopeHandling
{
//inject beans and test them
}
//starts the container once (for the whole suite)
@RunWith(CdiTestSuiteRunner.class)
@Suite.SuiteClasses({
SimpleTest.class,
SimpleTestControlTest.class
})
public class SuiteLevelContainerControl
{
}
//fine-grained project-stage control
@RunWith(CdiTestRunner.class)
@TestControl(projectStage = CustomTestStage.class) //default: ProjectStage.UnitTest.class
public class TestStageControl
{
//tests here will see project-stage CustomTestStage.class
@Test
@TestControl(projectStage = ProjectStage.Development.class)
public void checkDevEnv()
{
}
//tests here will see project-stage CustomTestStage.class
}


Update:
This add-on is part of all versions of DeltaSpike after v0.5