extending wildfly
DESCRIPTION
Presentation by Tomaz Cerar (Red Hat), delivered at the London JBoss User Group event on the 12th of February 2014. Watch the video here: http://www.youtube.com/watch?v=eu9K5NLUKBI Join London JBUG: http://www.c2b2.co.uk/jbugTRANSCRIPT
Extending WildFly
Tomaž Cerar, Red Hat
Agenda
• What are extensions• WildFly core• Write simple extension• Silly deployment detector• Demo
What are extensions?
• Entry point for extending WildFly• Can provide
– new deployment types– new model– services– resources
WILDFLY CORE
WildFly core
• Really small (< 15 mb)• Consists of
– JBoss Modules– Modular Service Controller (MSC)– Domain management (CLI, rest)– Deployment manager– Logging
JBoss Modules
• Modular class loader• Isolated class loader• Can be a set of many resources (jars)
Domain management
• Manages configuration• Backbone for all extensions• Accessible via
– Extensions– CLI– Admin console– DMR clients– …
MSC
• Truly concurrent service container• Handles service dependencies• Handles lifecycle• “real” functionality should be in services
DMR
• Detyped Model Representation• JSON like• Internal format for all operations• Internal model (ModelNode)
Domain model definition
• Attributes• Resources• Resource tree
– PathElement– Single target (key=value)– Multi target (key=*)
• Resolvers & multi language support
Operation handlers
• Defines operations on resources• Execution stage
– MODEL– RUNTIME– VERIFY– DOMAIN– DONE
• Can be chained
Resource handlers
• Every resource needs add & remove• In MODEL phase
– validate and set model• In RUNTIME phase
– Add services– Add deployment processors
Deployment manager
• Deployment repository• Defines deployment phases• Provides deployment processor
infrastructure• Can be used via
– Domain management– Deployment scanner
Deployment processor
• Hooks into deployment lifecycle• Can modify deployment behavior• Can define new deployment type
Extension point
• Loaded via Service Loader• Can define many subsystems• Packaged as JBoss Module• Referenced in configuration• Can provide any new functionality
Extension loading
standalone.xml<extension module="org.wildfly.extension.sdd"/>
ServiceLoaderorg.jboss.as.controller.Extension
org.wildfly.extension.sdd.SDDExtension
WRITE SIMPLE EXTENSION
Building blocks
• Define Extension point• Define Root Model• Define Add handler• Define XML parser • Define XML marshaller
Extension class
public class SDDExtension implements Extension {@Overridepublic void initializeParsers(ExtensionParsingContext context) {
}
@Overridepublic void initialize(ExtensionContext context) {
}}
Service Loader entry
• Point it to implementation class– org.wildfly.extension.sdd.SDDExtension
Define root modelpublic class SDDRootResource extends PersistentResourceDefinition {
static final SDDRootResource INSTANCE = new SDDRootResource();
private SDDRootResource() {super(SDDExtension.SUBSYSTEM_PATH,
SDDExtension.getResolver(),new SDDSubsystemAdd(),ReloadRequiredRemoveStepHandler.INSTANCE);
}
@Overridepublic void registerOperations(ManagementResourceRegistration resourceRegistration) {
super.registerOperations(resourceRegistration); resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE, false);
}}
Define root add handler
public class SDDSubsystemAdd extends AbstractBoottimeAddStepHandler {
@Overrideprotected void populateModel(ModelNode operation, ModelNode model) throws OperationFailedException
{model.setEmptyObject();
}
Define namespace
enum Namespace {
// must be firstUNKNOWN(null),
SDD_1_0("urn:wildfly:domain:sdd:1.0");
/*** The current namespace version.*/
public static final Namespace CURRENT = SDD_1_0;
private final String name;
Namespace(final String name) {this.name = name;
}}
Define XML model
<subsystem xmlns="urn:wildfly:domain:sdd:1.0"/>
Define parserclass SDDSubsystemParser implements XMLStreamConstants, XMLElementReader<List<ModelNode>> {
static final PersistentResourceXMLDescription xmlDescription = builder(SDDRootResource.INSTANCE).build();
@Overridepublic void readElement(XMLExtendedStreamReader reader, List<ModelNode>
list) throws XMLStreamException {xmlDescription.parse(reader, PathAddress.EMPTY_ADDRESS, list);
}}
Define marshaller
public void writeContent(XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException {
context.startSubsystemElement(Namespace.CURRENT.getUriString(), false);writer.writeEndElement();
}
Making it all work@Override
public void initializeParsers(ExtensionParsingContext context) {context.setSubsystemXmlMapping(SUBSYSTEM_NAME, Namespace.SDD_1_0.getUriString(),
SDDSubsystemParser.INSTANCE);}
@Overridepublic void initialize(ExtensionContext context) {
final SubsystemRegistration subsystem = context.registerSubsystem(SUBSYSTEM_NAME, 1, 0, 0);
final ManagementResourceRegistration registration =
subsystem.registerSubsystemModel(SDDRootResource.INSTANCE);
subsystem.registerXMLElementWriter(SDDSubsystemParser.INSTANCE);}
Module definition<module xmlns="urn:jboss:module:1.1" name="org.wildfly.extension.sdd">
<resources><resource-root path="wildfly-sdd-1.0.0.Alpha1-SNAPSHOT.jar"/>
</resources><dependencies>
<module name="javax.annotation.api"/><module name="javax.api"/><module name="org.jboss.jandex"/><module name="org.jboss.staxmapper"/><module name="org.jboss.as.controller"/><module name="org.jboss.as.server"/><module name="org.jboss.modules"/><module name="org.jboss.msc"/><module name="org.jboss.vfs"/><module name="org.jboss.logging"/>
</dependencies></module>
Module layout
What does it do?
Nothing!
How to test it?
• Test harness enables you to test– xml parser– model consistency– MSC services– Compatibility (transformers)– Localization resources– …
public class SDDSubsystemTestCase extends AbstractSubsystemBaseTest {
public SDDSubsystemTestCase() {super(SDDExtension.SUBSYSTEM_NAME, new SDDExtension());
}
@Overrideprotected String getSubsystemXml() throws IOException {
return readResource("sdd-1.0.xml");}
}
SILLY DEPLOYMENT DETECTOR
Let’s have subsystem that will detect common problems in deployments.
Silly deployment detector
• Idea come from forums• Should be able to detect
– Redundant JARs– Blacklisted jars– Bundling provided classes/packages– Common xml misconfigurations– …
Black listed jar detector
• You configure blacklisted jar names• Subsystem warns you if they are found
What we need
• Domain model• XML parser to handle new model• Deployment processor
Model definitionclass JarBlackListResourceDefinition extends SimpleResourceDefinition {
static final JarBlackListResourceDefinition INSTANCE = new JarBlackListResourceDefinition();private static final StringListAttributeDefinition JAR_NAMES =
new StringListAttributeDefinition.Builder("jar-names").setAllowNull(false).setXmlName("jars") .build();
private JarBlackListResourceDefinition() {super(SDDExtension.JAR_BLACKLIST_PATH,
SDDExtension.getResolver(),new JarBlackListAdd(),ReloadRequiredRemoveStepHandler.INSTANCE);
}
@Overridepublic void registerAttributes(ManagementResourceRegistration resourceRegistration) {
resourceRegistration.registerReadWriteAttribute(JAR_NAMES, null, new ReloadRequiredWriteAttributeHandler(JAR_NAMES));
}
XML
<subsystem xmlns="urn:wildfly:domain:sdd:1.0"><blacklist jars="mail-*.jar,activation*.jar,javassist-*.jar,jgroups-*.jar,jboss-logging-*.jar"/>
</subsystem>
Deployment processor
• Needs to check all jars in deployment• Compare them with blacklist
Demo
• https://github.com/ctomc/wildfly-sdd
• https://github.com/wildfly/wildfly
• http://www.wildfly.org/
Questions?