Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WFCORE-3751 DefaultCapabilityReferenceRecorder generates wrong dependent name if corresponding RuntimeCapability uses a dynamic name mapper #3216

Merged
merged 7 commits into from Jun 15, 2018

Conversation

pferraro
Copy link
Contributor

@wildfly-ci
Copy link

Core - Full Integration Build 7111 outcome was UNKNOWN using a merge of 3d2eeb7
Summary: Canceled (Error while applying patch; cannot find commit 07866ed in the https://github.com/wildfly/wildfly-core.git repository, possible reason: refs/pull/3216/merge branch was updated and the commit selected for the ... Build time: 00:00:08

*/
String getDynamicDependentName(PathAddress currentAddress) {
@Deprecated String getDynamicDependentName(PathAddress currentAddress) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a (package) method. If it is no longer used, we can delete it instead of deprecating it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's true. I'll remove it.

dependentName = baseDependentName;
}
RuntimeCapability<?> dependentCapability = this.getDependentCapability(context);
String dependentName = (dependentCapability.isDynamicallyNamed() ? dependentCapability.fromBaseCapability(context.getCurrentAddress()) : dependentCapability).getName();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main change is here.

Before, we were checking if the dependent capability was dynamic (according to the author) to be able to build its name.
Now, we fetch the dependent RuntimeCapability according to the current OperationContext MRR and build its name according to the MRR capabilities.

It is similar to the ContextDependencyRecorder implementation (although its getDependentCapability impl differs a bit as it checks there is a single registered capability).

My concern is the warning in ContextDependencyRecorder javadoc:

CapabilityReferenceRecorder that determines the dependent capability from the OperationContext. This assumes that the resource registration associated with currently executing step will expose a capability set including one and only one capability. This recorder cannot be used with attributes associated with resources that do not meet this requirement.

Your change to the DefaultCapabilityReferenceRecorder generalises the requirement of the ContextDependencyRecorder as the MRR can contain several capabilities and you only use the one corresponding to the baseDependentName.

Is my understanding correct?
Is there still a sense to have separate DefaultCapabilityReferenceRecorder and ContextDependencyRecorder as they now both require a Context MRR to work.
We could have a special case for attribute-based capability but that's a special case of your general DefaultCapabilityReferenceRecorder now, right?

Copy link
Contributor Author

@pferraro pferraro Apr 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your understanding is correct. In retrospect, DefaultCapabilityReferenceRecorder should probably extend ContextDependencyRecorder, and just override its logic for generating the dependent name (i.e. from a specific baseDependentName). Done.

Is there still a sense to have separate DefaultCapabilityReferenceRecorder and ContextDependencyRecorder

A valid question. Personally, I didn't even know that ContextDependencyRecorder existed until this week :) - so I don't know how many people are using it.
ContextDependencyRecorder requires fewer parameters, which is nice, but it can't be used if the resource defines multiple capabilities.
I suspect it is worth having both - but we should at least consolidate the implementations.

Another logical implementation is one that accepts the RuntimeCapability itself (this is how the CapabilityReferenceRecorder in wildfly-clustering-common works), which simplifies the getDependentCapability(...) even further (and without an exception case), but that is probably out of scope for this fix.

We could have a special case for attribute-based capability

What do you mean by attribute-based capability?

Copy link
Contributor Author

@pferraro pferraro Apr 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah - maybe you mean CompositeAttributeDependencyRecorder?

return capability;
}
}
throw ControllerLogger.ROOT_LOGGER.unknownCapability(this.baseDependentName);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we pass the OperationContext address to the exception so that the users can identify which resource is causing the issue?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could - but unless the same capability is defined by multiple resources (which is rare), the problematic resource is usually obvious.

@@ -73,7 +73,7 @@
public static final SimpleAttributeDefinition SECURITY_DOMAIN = new SimpleAttributeDefinitionBuilder(ModelDescriptionConstants.SECURITY_DOMAIN, ModelType.STRING, false)
.setMinSize(1)
.setFlags(AttributeAccess.Flag.RESTART_RESOURCE_SERVICES)
.setCapabilityReference(SECURITY_DOMAIN_CAPABILITY, MANAGEMENT_IDENTITY_CAPABILITY, false)
.setCapabilityReference(SECURITY_DOMAIN_CAPABILITY, MANAGEMENT_IDENTITY_CAPABILITY)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

juste a note that I much prefer to let the CapabilityReference determines where the dependent capability is dynamic or not according to the registered RuntimeCapability instead to have to specify it myself when I set the capability reference :)

.setAddRestartLevel(OperationEntry.Flag.RESTART_NONE)
.setRemoveRestartLevel(OperationEntry.Flag.RESTART_RESOURCE_SERVICES)
.setCapabilities(MANAGEMENT_IDENTITY_RUNTIME_CAPABILITY)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is your change equivalent?

Capability added to the ReloadRequiredRemoveStepHandler will be handled in org.jboss.as.controller.AbstractRemoveStepHandler#recordCapabilitiesAndRequirements that does a whole lot more that when you set it on the resource definition where it is handled in org.jboss.as.controller.SimpleResourceDefinition#registerCapabilities.

I agree with your change in principle as I think the capabilities belongs to the resource and not to its add/remove operation. However, are we missing some process from org.jboss.as.controller.AbstractRemoveStepHandler#recordCapabilitiesAndRequirements in doing so?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, right.

So my question is not specific to your PR but more generally why have we 2 different ways to specify capabilities (either in add/remove handler or in the resource definition)?
In any case, your PR is fine wrt that issue

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jmesnil That's just a matter of code history; in the initial cap/req code there was no MRR.getCapabilities(); the relevant caps were stored in the 'capabilities' field in the add/remove handlers.

@@ -120,6 +120,10 @@
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should it be in <scope>test</scope> ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops - yes, absolutely.

@@ -518,6 +522,10 @@ public void execute(ModelNode operation, OperationMessageHandler handler, ProxyO
private OperationStepHandler nextStep;
protected MockOperationContext(final Resource root, final boolean booting, final PathAddress operationAddress) {
super(root, booting, operationAddress);
Set<RuntimeCapability> capabilities = new HashSet<>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That goes back to my concern in the DefaultCapabilityReferenceRecorder implementation that now requires to get info from the MRR.

I am not sure if that's a constraint that will always be there. (it used to be absent in this test fixture for example).

Copy link
Contributor Author

@pferraro pferraro Apr 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Supplying capabilities to the add/remove operation handler is redundant. As I understand it, not registering a capability with the MMR is a bug.

@jmesnil
Copy link
Member

jmesnil commented Apr 19, 2018

@pferraro After finishing my review, your PR looks right except for the added requirement to always get RuntimeCapability info from the MRR in the DefaultCapabilityReferenceRecorder implementation.

@ehsavoie @bstansberry Do you have an use case where this would not be the case?

The tests were such a case but I don't know if that was by design or just because it was not needed to get info from the MRR.

@bstansberry
Copy link
Contributor

@jmesnil The main way the cap would not be in the MRR is if people relied on the old code that passed the relevant caps to the Abstract[Add|Remove]StepHandler constructor and didn't record the cap with the MRR.

That would largely be a bug, as not recording with the MRR means the possible capability info is not available. I don't think it's done in WF code but it might be done in downstream projects that haven't kept up with best practices.

I say "largely a bug" because we've contemplated having a capability only registered if an attribute is set to a particular value. For example jts=true in subsystem=transactions, when we get around to doing caps in that subsystem. But:

  1. I think using an attribute that way is wrong. Registering an actual capability should simply be due to adding the resource. The tx subsystem should use a child resource for jts. (Note this rule means the new management-api javadoc at https://github.com/bstansberry/wildfly-core/blob/new-mgmt-api/management-api/src/main/java/org/wildfly/management/api/capability/CapabilityRegistrar.java#L29 needs to be changed, as there's no such thing as an "optional capability".)

  2. Even if we say using an attribute that way is ok it doesn't mean the MRR shouldn't mention the cap and thus expose it as a possible capability. It just means the add handler would need to specially handle registering the actual capability.

@pferraro if we do this we need to deprecate all the add/remove handler constructors in the controller module that accept a RuntimeCapability param. Their presence obscures that the caps to register really should come from the MRR.

Finally, I think this will avoid breaking any downstream code that isn't properly registering the cap with the MRR:

d98a563

@wildfly-ci
Copy link

Core - Full Integration Build 7247 outcome was UNKNOWN using a merge of e70c52f
Summary: Canceled (Error while applying patch; cannot find commit 73fc467 in the https://github.com/wildfly/wildfly-core.git repository, possible reason: refs/pull/3216/merge branch was updated and the commit selected for the ... Build time: 00:00:13

@ehsavoie
Copy link
Contributor

AbstractBoottimeAddStepHandler, ReloadRequiredAddStepHandler, ReloadRequiredRemoveStepHandler , ServiceRemoveStepHandler constructors with capabilities should be deprecated too.
Otherwise +1

@pferraro
Copy link
Contributor Author

pferraro commented Jun 1, 2018

@jmesnil @ehsavoie Suggested changes incorporated.

@wildfly-ci
Copy link

Core - Full Integration Build 7484 outcome was FAILURE using a merge of dd1af51
Summary: Tests failed: 1, passed: 4341, ignored: 142 Build time: 01:32:53

Failed tests

org.jboss.as.test.clustering.cluster.web.ConcurrentFineWebFailoverTestCase.test: java.lang.AssertionError: expected:<200> but was:<500>
	at org.jboss.as.test.clustering.ClusterHttpClientUtil.establishTopology(ClusterHttpClientUtil.java:69)
	at org.jboss.as.test.clustering.ClusterHttpClientUtil.establishTopology(ClusterHttpClientUtil.java:58)
	at org.jboss.as.test.clustering.ClusterHttpClientUtil.establishTopology(ClusterHttpClientUtil.java:52)
	at org.jboss.as.test.clustering.cluster.web.AbstractWebFailoverTestCase.establishTopology(AbstractWebFailoverTestCase.java:360)
	at org.jboss.as.test.clustering.cluster.web.AbstractWebFailoverTestCase.testFailover(AbstractWebFailoverTestCase.java:120)
	at org.jboss.as.test.clustering.cluster.web.AbstractWebFailoverTestCase.testGracefulUndeployFailover(AbstractWebFailoverTestCase.java:112)
	at org.jboss.as.test.clustering.cluster.web.AbstractWebFailoverTestCase.test(AbstractWebFailoverTestCase.java:103)
------- Stdout: -------
 [0m18:10:55,735 INFO  [org.jboss.as.repository] (management-handler-thread - 2) WFLYDR0001: Content added at location /store/work/tc-work/37b47ae8b9c60325/full/testsuite/integration/clustering/target/wildfly-1/standalone/data/content/b9/636e6071b3b98f033917520339474c469ca9b1/content
 [0m [0m18:10:55,738 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-1) WFLYSRV0027: Starting deployment of "ConcurrentFineWebFailoverTestCase.war" (runtime-name: "ConcurrentFineWebFailoverTestCase.war")
 [0m [33m18:10:55,869 WARN  [org.jboss.as.dependency.private] (MSC service thread 1-1) WFLYSRV0018: Deployment "deployment.ConcurrentFineWebFailoverTestCase.war" is using a private module ("org.jboss.as.clustering.common") which may be changed or removed in future versions without notice.
 [0m [33m18:10:55,869 WARN  [org.jboss.as.dependency.private] (MSC service thread 1-1) WFLYSRV0018: Deployment "deployment.ConcurrentFineWebFailoverTestCase.war" is using a private module ("org.jboss.as.controller") which may be changed or removed in future versions without notice.
 [0m [33m18:10:55,869 WARN  [org.jboss.as.dependency.private] (MSC service thread 1-1) WFLYSRV0018: Deployment "deployment.ConcurrentFineWebFailoverTestCase.war" is using a private module ("org.jboss.as.server") which may be changed or removed in future versions without notice.
 [0m [33m18:10:55,869 WARN  [org.jboss.as.dependency.private] (MSC service thread 1-1) WFLYSRV0018: Deployment "deployment.ConcurrentFineWebFailoverTestCase.war" is using a private module ("org.infinispan") which may be changed or removed in future versions without notice.
 [0m [33m18:10:55,869 WARN  [org.jboss.as.dependency.private] (MSC service thread 1-1) WFLYSRV0018: Deployment "deployment.ConcurrentFineWebFailoverTestCase.war" is using a private module ("org.wildfly.clustering.infinispan.spi") which may be changed or removed in future versions without notice.
 [0m [0m18:10:55,893 INFO  [org.jboss.weld.deployer] (MSC service thread 1-1) WFLYWELD0003: Processing weld deployment ConcurrentFineWebFailoverTestCase.war
 [0m [0m18:10:55,941 INFO  [org.hibernate.validator.internal.util.Version] (MSC service thread 1-1) HV000001: Hibernate Validator 5.3.6.Final
 [0m [0m18:10:56,002 INFO  [org.jboss.as.ejb3.deployment] (MSC service thread 1-1) WFLYEJB0473: JNDI bindings for session bean named 'TopologyChangeListenerBean' in deployment unit 'deployment "ConcurrentFineWebFailoverTestCase.war"' are as follows:

	java:global/ConcurrentFineWebFailoverTestCase/TopologyChangeListenerBean!org.jboss.as.test.clustering.TopologyChangeListener
	java:app/ConcurrentFineWebFailoverTestCase/TopologyChangeListenerBean!org.jboss.as.test.clustering.TopologyChangeListener
	java:module/TopologyChangeListenerBean!org.jboss.as.test.clustering.TopologyChangeListener
	java:jboss/exported/ConcurrentFineWebFailoverTestCase/TopologyChangeListenerBean!org.jboss.as.test.clustering.TopologyChangeListener
	ejb:ConcurrentFineWebFailoverTestCase/TopologyChangeListenerBean!org.jboss.as.test.clustering.TopologyChangeListener
	java:global/ConcurrentFineWebFailoverTestCase/TopologyChangeListenerBean
	java:app/ConcurrentFineWebFailoverTestCase/TopologyChangeListenerBean
	java:module/TopologyChangeListenerBean

 [0m [0m18:10:56,109 INFO  [org.jboss.weld.Version] (MSC service thread 1-1) WELD-000900: 3.0.4 (Final)
 [0m [0m18:10:56,228 INFO  [org.jboss.as.clustering.infinispan] (ServerService Thread Pool -- 21) WFLYCLINF0002: Started default-server cache from web container
 [0m [0m18:10:56,247 INFO  [org.jboss.as.clustering.infinispan] (ServerService Thread Pool -- 14) WFLYCLINF0002: Started ConcurrentFineWebFailoverTestCase.war cache from web container
 [0m [33m18:10:56,413 WARN  [org.jboss.weld.Bootstrap] (MSC service thread 1-6) WELD-000146: BeforeBeanDiscovery.addAnnotatedType(AnnotatedType<?>) used for class org.hibernate.validator.internal.cdi.interceptor.ValidationInterceptor is deprecated from CDI 1.1!
 [0m [33m18:10:56,423 WARN  [org.jboss.weld.Bootstrap] (MSC service thread 1-6) WELD-000146: BeforeBeanDiscovery.addAnnotatedType(AnnotatedType<?>) used for class org.jberet.creation.BatchBeanProducer is deprecated from CDI 1.1!
 [0m [0m18:10:56,780 INFO  [org.wildfly.extension.undertow] (ServerService Thread Pool -- 2) WFLYUT0021: Registered web context: '/ConcurrentFineWebFailoverTestCase' for server 'default-server'
 [0m [0m18:10:56,798 INFO  [org.jboss.as.server] (management-handler-thread - 2) WFLYSRV0010: Deployed "ConcurrentFineWebFailoverTestCase.war" (runtime-name : "ConcurrentFineWebFailoverTestCase.war")
 [0m [0m18:10:56,881 INFO  [org.jboss.as.repository] (management-handler-thread - 1) WFLYDR0001: Content added at location /store/work/tc-work/37b47ae8b9c60325/full/testsuite/integration/clustering/target/wildfly-2/standalone/data/content/aa/2952c67eb5a4021508f7e4c6be60bb1412890c/content
 [0m [0m18:10:56,883 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-3) WFLYSRV0027: Starting deployment of "ConcurrentFineWebFailoverTestCase.war" (runtime-name: "ConcurrentFineWebFailoverTestCase.war")
 [0m [33m18:10:56,957 WARN  [org.jboss.as.dependency.private] (MSC service thread 1-5) WFLYSRV0018: Deployment "deployment.ConcurrentFineWebFailoverTestCase.war" is using a private module ("org.jboss.as.clustering.common") which may be changed or removed in future versions without notice.
 [0m [33m18:10:56,958 WARN  [org.jboss.as.dependency.private] (MSC service thread 1-5) WFLYSRV0018: Deployment "deployment.ConcurrentFineWebFailoverTestCase.war" is using a private module ("org.jboss.as.controller") which may be changed or removed in future versions without notice.
 [0m [33m18:10:56,958 WARN  [org.jboss.as.dependency.private] (MSC service thread 1-5) WFLYSRV0018: Deployment "deployment.ConcurrentFineWebFailoverTestCase.war" is using a private module ("org.jboss.as.server") which may be changed or removed in future versions without notice.
 [0m [33m18:10:56,958 WARN  [org.jboss.as.dependency.private] (MSC service thread 1-5) WFLYSRV0018: Deployment "deployment.ConcurrentFineWebFailoverTestCase.war" is using a private module ("org.infinispan") which may be changed or removed in future versions without notice.
 [0m [33m18:10:56,958 WARN  [org.jboss.as.dependency.private] (MSC service thread 1-5) WFLYSRV0018: Deployment "deployment.ConcurrentFineWebFailoverTestCase.war" is using a private module ("org.wildfly.clustering.infinispan.spi") which may be changed or removed in future versions without notice.
 [0m [0m18:10:56,988 INFO  [org.jboss.weld.deployer] (MSC service thread 1-3) WFLYWELD0003: Processing weld deployment ConcurrentFineWebFailoverTestCase.war
 [0m [0m18:10:57,033 INFO  [org.hibernate.validator.internal.util.Version] (MSC service thread 1-3) HV000001: Hibernate Validator 5.3.6.Final
 [0m [0m18:10:57,093 INFO  [org.jboss.as.ejb3.deployment] (MSC service thread 1-3) WFLYEJB0473: JNDI bindings for session bean named 'TopologyChangeListenerBean' in deployment unit 'deployment "ConcurrentFineWebFailoverTestCase.war"' are as follows:

	java:global/ConcurrentFineWebFailoverTestCase/TopologyChangeListenerBean!org.jboss.as.test.clustering.TopologyChangeListener
	java:app/ConcurrentFineWebFailoverTestCase/TopologyChangeListenerBean!org.jboss.as.test.clustering.TopologyChangeListener
	java:module/TopologyChangeListenerBean!org.jboss.as.test.clustering.TopologyChangeListener
	java:jboss/exported/ConcurrentFineWebFailoverTestCase/TopologyChangeListenerBean!org.jboss.as.test.clustering.TopologyChangeListener


@jmesnil
Copy link
Member

jmesnil commented Jun 8, 2018

@pferraro I'm looking at merging this PR.
It seems you have not cherry-picked (or squashed) d98a563 as brian proposed. Is that correct?

@pferraro
Copy link
Contributor Author

pferraro commented Jun 8, 2018

@jmesnil I've cherry-picked it into this PR.

@jmesnil jmesnil added the ready-for-merge This PR is ready to be merged and fulfills all requirements label Jun 15, 2018
@jmesnil jmesnil merged commit 59e9de5 into wildfly:master Jun 15, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready-for-merge This PR is ready to be merged and fulfills all requirements
Projects
None yet
5 participants