Playx
Bring some of Javax to Play!
Servlet
<dependency>
<groupId>com.github.rmannibucau</groupId>
<artifactId>playx-servlet</artifactId>
<version>${playx.version}</version>
</dependency>
Servlet integration brings the ability to use play as a servlet container.
Setup:
-
Bind a
PlayServletContext
in your IoC to letServletFilter
get injected - we assume you are using Guice here:
public class ServletModule extends AbstractModule {
@Override
protected void configure() {
bind(PlayServletContext.class);
bind(PlayServletContext.class).toInstance(servletContext);
}
}
-
You can bind servlets to the context using a
ServletContainerInitializer
or directly defining servlets. To use an initializer, register it through the related config entry;:
playx.servlet.initializers += org.app.MyInitializer
An implementation can look like:
public class Setup implements ServletContainerInitializer {
@Override
public void onStartup(final Set<Class<?>> c, final ServletContext servletContext) {
{
final ServletRegistration.Dynamic servlet = servletContext.addServlet("async", new AsyncServlet());
servlet.addMapping("/async");
servlet.setAsyncSupported(true);
}
{
final ServletRegistration.Dynamic servlet = servletContext.addServlet("asyncdispatch",
new AsyncDispatchServlet());
servlet.addMapping("/asyncdispatch");
servlet.setAsyncSupported(true);
}
{
servletContext.addServlet("sync", new SyncServlet()).addMapping("/sync");
}
}
}
-
Bind the
ServletFilter
in your configuration, this is the one responsible to route the requests to the servlet context when relevant (depending the mapping):
play.filters.enabled.1000 = com.github.rmannibucau.playx.servlet.servlet.api.ServletFilter
Important
|
the number at the end is the position of the filter in the list, it is highly recommanded to put it last since it acts as an endpoint and must stay after security filters when in use, if you use a custom DefaultFilters ensure it is at the last position. |
Known limitations
-
No filter support (yet)
-
No WebListener support (yet)
-
HandlesTypes is not supported yet
Configuration
playx {
servlet {
context = "" // the servlet context to use, default is root
executor { // configure the pool used for the servlet operation
core = 64 // when default = false it is the core size of the pool
max = 128 // when default = false it is the max size of the pool
keepAlive { // how long a thread is kept idle in the pool
value = 60
unit = SECONDS
}
}
initializers = [
org.app.Initializer
]
listeners = [
app.MyContextListener
]
filters = [
{
name: "my-fitler",
className: "my.FilterImpl",
asyncSupported: true,
initParameters: [
{ name: "the key", value: "the value" }
]
}
]
servlets = [
{
name: "my-servlet",
className: "my.ServletImpl",
asyncSupported: true,
loadOnStartup: 1,
initParameters: [
{ name: "the key", value: "the value" }
]
}
]
}
}
IoC
<dependency>
<groupId>com.github.rmannibucau</groupId>
<artifactId>playx-ioc</artifactId>
<version>${playx.version}</version>
</dependency>
This module provides some way to setup a generic IoC and delegate the logic to multiple implementations.
Configuration
// force play to use the playx implementation
play.application.loader = com.github.rmannibucau.playx.ioc.IoCLoader
// configure the loaders to use
playx {
ioc {
loaders = [
play.inject.guice.GuiceApplicationLoader,
my.container.MyApplicationLoader
]
// you can specify a preference for the IoC by package
// the key is the package (subpackages are included) and the value
// a string contained in the lowercased loader simple name (must not be ambiguous)
routing = [
{ "org.superbiz": "guice" },
{ "com.app": "my" }
]
}
}
The Application
loaded by the IoCLoader
will be the first one in the list.
CDI
<dependency>
<groupId>com.github.rmannibucau</groupId>
<artifactId>playx-cdi</artifactId>
<version>${playx.version}</version>
</dependency>
The CDI module allows to start a CDI 2.0 standalone container and use it either with ioc module or just as a contextual CDI (i.e. not linked to play IoC but embedded in play).
Important
|
the play IoC model being very tight to Guice due its module definition which is not supported yet in CDI integration, you can need to define some play beans to use it as the main and unique loader for your application. |
This module doesn’t provide any CDI API not implementation to let you plug the one you prefer (Apache OpenWebBeans is recommanded since default setup is done for play but Weld works too). The dependency to add is the CDI SE module (openwebbeans-se
for instance).
Warning
|
since generally applications rely on a Guice version of the play JSR-330 integration and since CDI scanning works great without that boilerplate, there is not yet a conversion of modules. However if you are interested in supporting play.modules.enabled you can write a custom CDI extension to do it. |
Configuration
Check out the javax.enterprise.inject.se.SeContainerInitializer
API for the meaning of each configuration entry.
play.application.loader = com.github.rmannibucau.playx.cdi.CdiLoader
playx {
cdi {
// same as play.allowGlobalApplication but for this IoC
allowGlobalApplication = false
beans { // should default play bean be added to CDI context
default = true
// provides a way to register custom beans, useful for not scanned modules
customs = [
// only className is mandatory
{
className: org.foo.MyBean,
scope: "javax.enterprise.context.Dependent",
id: "custom.org.foo.MyBean",
transitiveTypeClosure: false
}
]
}
container { // all is optional
disableDiscovery = false,
beanClasses = [
com.app.Foo,
com.app.Bar
],
packages = [
org.superbiz, // shortcut for next line syntax with recursive=false
{ package: "org.apache.deltaspike", recursive: true }
],
properties = [ // mainly vendor specific
{ key: "foo", value: "bar" }
],
extensions = [
org.apache.deltaspike.core.api.provider.BeanManagerProvider,
org.apache.deltaspike.core.impl.config.ConfigurationExtension,
org.apache.deltaspike.core.impl.jmx.MBeanExtension,
org.apache.johnzon.jsonb.cdi.JohnzonCdiExtension
],
decorators = [
org.app.MyDecorator
],
interceptor = [
org.app.MyInterceptor
],
alternatives = [
org.app.MyAlternative
],
alternativeStereotypes = [
org.app.MyStereotype
]
}
}
Microprofile Config
<dependency>
<groupId>com.github.rmannibucau</groupId>
<artifactId>playx-microprofile-config</artifactId>
<version>${playx.version}</version>
</dependency>
This module adds a Microprofile Configuration ConfigSource
using CDI to look up a typesafe Config
to get configurations. It support primitives, objects and list of primitives (but not list of object) and flatten the configuration keys.
For instance:
app {
service {
url = "http://remote"
}
}
Will provide the following configurations:
app.service.url = http://remote
So you can use it through:
@Inject
@ConfigProperty(name = "app.service.url")
private String url;
Swagger Integration
<dependency>
<groupId>com.github.rmannibucau</groupId>
<artifactId>playx-swagger</artifactId>
<version>${playx.version}</version>
</dependency>
Playx Swagger extends play-swagger module to support to enrich swagger with custom swagger readers. It requires to provide a reader class with a read(Set<Class<?>>)
method and taking a Swagger
instance in its constructor.
swagger.api.additional = [
{
reader: "io.swagger.jaxrs.Reader",
prefix: "/api", // prefixes all operation paths, default to empty
classes: [
"app.MyJaxRsEndpoint1",
"app.MyJaxRsEndpoint2",
"app.MyJaxRsEndpoint3"
]
}
]