[wildfly-dev] Capabilit integration from services and DeploymentUnitProcessors
Brian Stansberry
brian.stansberry at redhat.com
Tue Jun 30 14:30:12 EDT 2015
tl;dr; DUPs may need access to the integration APIs provided by
capabilities. I've got a first cut solution to that, but there are edge
cases that don't work well and we may need to restrict how capabilities
work a bit.
Long version.
WildFly Core capabilities are meant to provide a standardized way for
parts of the server to integrate with each other.[1]
Use of these is proceeding pretty nicely in the OperationStepHandlers
the kernel and subsystems use for executing management operations. But
in some cases, the code that needs to integrate with a capability isn't
in an OSH. It can be in a service start method, particularly in a
DeploymentUnitProcessor. (DUPs run in a service start method.)
A simple example would be a deployment descriptor or annotation includes
a chunk of config that specifies the use of a subsystem-provided
resource, say a cache. The DUP then wants to figure out the service name
of that resource, using capabilities.
So I've started to give some thought to how to handle that. See
https://github.com/bstansberry/wildfly-core/commit/ba7321bc30374b2d0aa99cbf344d50b50fa2eea6
for a first cut.
Basically the OperationContext exposes a "CapabilityServiceSupport"
object that OSHs can provide to services they install. The services can
then use that to look up service names and any custom runtime API
provided by a capability.
Typical pattern would be the OSH for a "deploy" op would make the
CapabilityServiceSupport available to RootDeploymentUnitService, which
would expose it to DUPs via a DeploymentPhaseContext attachment. DUPs,
as they install services would use the CapabilityServiceSupport to look
up service names and add dependencies to that new service.
The service doesn't register any requirement for the capability. If it
tries to use a non-existent capability, an exception is thrown and the
service has to deal with it. *This is the main problem.* The caller is
unable to register a dependency (since it can't get the service name) so
the MSC behavior of letting the service be installed but fail to start
due to a missing dependency is short circuited.
In most cases, if a service is installed but fails to start due to a
missing dependency, the management op that installed it is rolled back,
so the end result is the same. But we do support the
"rollback-on-runtime-failure=false" management op header, and if that's
used our behavior would be changed for the worse.
A possible partial solution to this would be to tighten down the rules
for how service names are created from capability names. Basically, any
capability could only provide 1 service, and the name of the service
would be the result of passing the name of the capability to
ServiceName.parse(name). That's the default behavior now, but we support
other options.
That would fix the service name discovery problem, by making the name
discovery algorithm completely static. It wouldn't help with a case
where a DUP needs access to a custom runtime API exposed by a
capability. But that is much more of a corner case. Probably better to
discuss on a sub branch of this thread. :)
What would we lose if we tightened down the service name rules?
1) Capabilities would not be able to tell the service name discovery
logic to produce some legacy service naming pattern (i.e. keep service
names as they were in earlier releases.)
This one I don't think is a big deal, as the capability can always
register an alias for the service that uses the legacy service name.
2) A capability cannot provide services of > 1 value type. It's nice if
capabilities can represent something that's meaningful to an end user,
and there's no reason why something that's meaningful to an end user
might not expose more than one service to other capabilities. If we
limit capabilities to exposing a single service, then we may end up with
multiple capabilities. See [2] for an example case, where a proposed
"org.wildfly.iiop" (nice and simple for an end user to understand)
installs two services, an ORB and a NamingContextExt.
At this point though, capability names aren't really exposed to end
users, so perhaps we can put this problem aside for now. If it becomes
an issue later, there are solutions, e.g. a user-friendly
"org.wildfly.iiop" capability automatically registers the detailed
"org.wildfly.iiop.orb" and "org.wildfly.iiop.naming" capabilities,
helping the user ignore the details.
Sorry for the long tome; by now I expect folks are used to it!
[1] Specifically, to validate that references to other parts of the
configuration are valid, to determine the names of MSC services provided
by other parts of the system, and to access any custom runtime
integration API exposed by another part of the system.
[2]
https://github.com/bstansberry/wildfly/commit/b9de64e046404531df466288cf4fb1f99b917636#diff-04ae38c6384a018059f5411e261f0d61R86
--
Brian Stansberry
Senior Principal Software Engineer
JBoss by Red Hat
More information about the wildfly-dev
mailing list