-
1. Re: problems with org.jboss.as package names in Wildfly
adinn Jan 26, 2016 10:56 AM (in response to rachmato)Hi Richard,
I don't know for sure what is happening here but I suspect that the problem is indeed to do with module loaders. If you could run with verbose output that might help diagnose the problem. You need to add -Dorg.jboss.byteman.verbose to the command line and then look to see if there are any messages in the AS log which refer to rule ManagedExecutorService_execute.
What I suspect to be the root of the problem here is that the jar which defines interface ManagedExecutorService is in a different module to the jar containing the class (or classes) which implements it. That might very well cause a problem trying to resolve a reference to the interface class either at injection time or at rule typecheck time.
If you can provide me with a simple set of instructions for reproducing the failure I will be very happy to investigate this further.
regards,
Andrew DInn
-
2. Re: problems with org.jboss.as package names in Wildfly
rachmato Jan 26, 2016 1:43 PM (in response to adinn)Hi Andrew
In trying to set up a simple example for you, I found that what I was claiming is not true in general.
Here is the script I used:
RULE org.jboss.as package example CLASS org.jboss.as.clustering.infinispan.subsystem.InfinispanSubsystemServiceHandler METHOD installServices AT ENTRY IF TRUE DO System.out.println("[BYTEMAN] Activating Infinispan subsystem") ENDRULE RULE org.wildfly package example CLASS org.wildfly.extension.undertow.UndertowService METHOD start AT ENTRY IF TRUE DO System.out.println("[BYTEMAN] Undertow starting") ENDRULE
These rules just duplicate some standard startup logging in the server which is going to be seen in any case.
Here are the results of starting Wildfly with the standalone-ha.xml configuration with the script: http://pastebin.com/TZdyatGu
I see that both the org.jboss.as rule and the org.wildfly rule both were executed as expected.
The earlier examples I mentioned involve instrumenting code in packages org.jboss.as which are started as on-demand services. These on-demand services are started upon deployment of an application. I'll try and concoct a better example. :-(
-
3. Re: problems with org.jboss.as package names in Wildfly
rachmato Jan 26, 2016 3:14 PM (in response to rachmato)I tried a second example, using this script, which has one rule added at the end:
RULE org.jboss.as package example CLASS org.jboss.as.clustering.infinispan.subsystem.InfinispanSubsystemServiceHandler METHOD installServices AT ENTRY IF TRUE DO System.out.println("[BYTEMAN] Activating Infinispan subsystem") ENDRULE RULE org.wildfly package example CLASS org.wildfly.extension.undertow.UndertowService METHOD start AT ENTRY IF TRUE DO System.out.println("[BYTEMAN] Undertow starting") ENDRULE RULE org.jboss.as on-demand package example CLASS org.jboss.as.ejb3.remote.protocol.versionone.VersionOneProtocolChannelReceiver METHOD startReceiving AT ENTRY IF TRUE DO System.out.println("[BYTEMAN] VersionOne receiving") ENDRULE
and starting the server by hand, we get this console output: http://pastebin.com/SCGHfMXc
We can see at the very end of the console output that the new rule has been activated. Which surprised me, as in all previous testing I was doing, using Arquillian based tests and SmartFrog based tests, those rules were not getting activated.
One more example to come.
-
4. Re: problems with org.jboss.as package names in Wildfly
rachmato Jan 26, 2016 3:59 PM (in response to rachmato)Well, there's good news and there's bad news. The good news is that after further testing, I have been able to show that instrumenting classes with org.jboss.as packages in Wildfly does work as expected, including from jobs controlled by Arquillian. The bad news is that the scripts I used originally, which "didn't work", now "work". Can't explain at the moment, other than I may have been running a test which did no pass through the code path which the rule applies to. But I seem to remember the Transformer statements in verbose mode just not being there for the rules that I thought were not working.
Anywaty,..., this case is closed. Thanks for your attention, Andrew.
-
5. Re: problems with org.jboss.as package names in Wildfly
adinn Jan 26, 2016 4:21 PM (in response to rachmato)No problem, Richard. If you manage to get this problem to recur enable verbose trace and let me know what it shows.
regards,
Andrew Dinn
-
6. Re: problems with org.jboss.as package names in Wildfly
rachmato Jan 27, 2016 3:05 PM (in response to adinn)Hi Andrew, back again :-(
I now have most of my rules set up (for instrumenting Wildfly classes) and I am running into another problem: getting access to method invocation parameters.
Here is a concrete example:
Rule:
RULE StatefulSessionComponent_destroyInstance CLASS org.jboss.as.ejb3.component.stateful.StatefulSessionComponent METHOD destroyInstance BIND id:String = $1.getId(); AT ENTRY IF TRUE DO # System.out.println("[BYTEMAN-StatefulSessionComponent] destroy instance, id: ") System.out.println("[BYTEMAN-StatefulSessionComponent] destroy instance, id: " + id) ENDRULE
The actual method code in the class:
@Override public void destroyInstance(StatefulSessionComponentInstance instance) { instance.setRemoved(true); if(!instance.isSynchronizationRegistered()) { instance.destroy(); } }
The error message when verbose is turned on:
14:45:42,224 INFO [stdout] (ServerService Thread Pool -- 17) Rule.execute called for SimpleCache_stop_5
14:45:42,224 INFO [stdout] (ServerService Thread Pool -- 17) SimpleCache_stop execute
14:45:42,224 INFO [stdout] (ServerService Thread Pool -- 17) [BYTEMAN-SimpleCache] stop cache
14:45:42,224 INFO [stdout] (ServerService Thread Pool -- 17) Rule.execute called for StatefulSessionComponent_destroyInstance_1
14:45:42,224 INFO [stdout] (ServerService Thread Pool -- 23) Rule.execute called for DistributableCache_stop_13
14:45:42,224 INFO [stdout] (ServerService Thread Pool -- 23) DistributableCache_stop execute
14:45:42,224 INFO [stdout] (ServerService Thread Pool -- 23) [BYTEMAN-DistributableCache] stop cache
14:45:42,225 INFO [org.jboss.as.clustering.infinispan] (ServerService Thread Pool -- 4) WFLYCLINF0003: Stopped stateful-failover.war cache from web container
14:45:42,225 INFO [stdout] (ServerService Thread Pool -- 17) Rule.ensureTypeCheckedCompiled : error type checking rule StatefulSessionComponent_destroyInstance
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) org.jboss.byteman.rule.exception.TypeException: MethodExpression.typeCheck : ambiguous method signature getId for target class org.jboss.as.ejb3.component.stateful.StatefulSessionComponentInstance file /home/nrla/byteman-scripts/script-server-cache.btm line 140
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.byteman.rule.expression.MethodExpression.findMethod(MethodExpression.java:325)
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.byteman.rule.expression.MethodExpression.typeCheck(MethodExpression.java:188)
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.byteman.rule.binding.Binding.typeCheck(Binding.java:131)
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.byteman.rule.Event.typeCheck(Event.java:114)
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.byteman.rule.Event.typeCheck(Event.java:106)
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.byteman.rule.Rule.typeCheck(Rule.java:521)
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.byteman.rule.Rule.ensureTypeCheckedCompiled(Rule.java:449)
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.byteman.rule.Rule.execute(Rule.java:672)
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.byteman.rule.Rule.execute(Rule.java:653)
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.as.ejb3.component.stateful.StatefulSessionComponent.destroyInstance(StatefulSessionComponent.java)
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.as.ejb3.component.stateful.StatefulSessionComponent.destroyInstance(StatefulSessionComponent.java:75)
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.as.ejb3.cache.simple.SimpleCache.stop(SimpleCache.java:91)
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.as.ejb3.component.stateful.StatefulSessionComponent.done(StatefulSessionComponent.java:369)
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.as.ejb3.component.EJBComponent.stop(EJBComponent.java:553)
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.as.ee.component.ComponentStartService$2.run(ComponentStartService.java:78)
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at java.util.concurrent.FutureTask.run(FutureTask.java:266)
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at java.lang.Thread.run(Thread.java:745)
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.threads.JBossThread.run(JBossThread.java:320)
14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17)
The class StatefulSessionComponentInstance is as follows:
public class StatefulSessionComponentInstance extends SessionBeanComponentInstance implements Identifiable<SessionID>, Contextual<Object> { private static final long serialVersionUID = 3803978357389448971L; private final SessionID id; [snip] @Override public SessionID getId() { return id; } [snip] }
I'm having similar problems with getting access to method parameters in other rules, but this is a typical example.
Any ideas on what i'm doing wrong?
-
7. Re: problems with org.jboss.as package names in Wildfly
jameslivingston Jan 27, 2016 5:00 PM (in response to rachmato)What is going wrong for you is an artifact of generic type erasure.
Simplified to the relevant parts, there is:
interface StatefulObjectFactory<T> {
void destroyInstance(T instance)
}
class StatefulSessionComponent implements StatefulObjectFactory<StatefulSessionComponentInstance> {
void destroyInstance(StatefulSessionComponentInstance instance) {...}
}
For StatefulObjectFactory, the T is erased to Object since there is no upper bound, so at the JVM class/bytecode method, the method's parameter is Object.
StatefulSessionComponent has a concrete type rather than a generic one for the type parameter, so the compiled version of the method written in the source code takes a StatefulSessionComponentInstance as a parameter. If you think about it, that means as-is StatefulSessionComponent does not implement the StatefulObjectFactory interface, because it does not implement the "void destroyInstance(Object)" method.
What happens is that the Java compiler inserts a synthetic bridge method, which forwards to the actual implementation after a cast:
void destroyInstance(Object o) { destroyInstance((StatefulSessionComponentInstance)o);}
So the compiled class actually has two destroyInstance methods, not one. Your rule does not specify any parameter types, so ByteMan intercepts both of them. When it triggers for the Object-parameter method, it fails to check because Object does not have a getId() method. Triggering for the StatefulSessionComponentInstance-parameter method would work.
So what you need to do is to change your rule to have "METHOD destroyInstance(StatefulSessionComponentInstance)", so it only triggers for the specialised one with the real implementation. If that ends up being called via the Object-parameter version, that is fine since it will trigger when it forwards to the other one.
-
8. Re: problems with org.jboss.as package names in Wildfly
rachmato Jan 27, 2016 6:50 PM (in response to jameslivingston)Hi James
Thanks very much for the comprehensive answer!
I made the changes and unless i'm again messing up, the same problem arises:
RULE StatefulSessionComponent_destroyInstance CLASS org.jboss.as.ejb3.component.stateful.StatefulSessionComponent METHOD destroyInstance(StatefulSessionComponentInstance) BIND appName:String = "<" + $this.getApplicationName() + "." + $this.getModuleName() + "." + $this.getDistinctName() + ">"; AT ENTRY IF TRUE DO System.out.println("[BYTEMAN-StatefulSessionComponent] destroy instance, id: " + $1.getId()) ENDRULE
In the logs:
18:42:58,789 INFO [stdout] (ServerService Thread Pool -- 22) Rule.execute called for StatefulSessionComponent_destroyInstance_1
18:42:58,789 INFO [stdout] (ServerService Thread Pool -- 6) [BYTEMAN-DistributableCache] stop cache
18:42:58,791 INFO [org.infinispan.eviction.impl.PassivationManagerImpl] (ServerService Thread Pool -- 71) ISPN000029: Passivating all entries to disk
18:42:58,791 INFO [stdout] (ServerService Thread Pool -- 22) Rule.ensureTypeCheckedCompiled : error type checking rule StatefulSessionComponent_destroyInstance
18:42:58,791 INFO [stdout] (ServerService Thread Pool -- 22) org.jboss.byteman.rule.exception.TypeException: MethodExpression.typeCheck : ambiguous method signature getId for target class org.jboss.as.ejb3.component.stateful.StatefulSessionComponentInstance file /home/nrla/byteman-scripts/script-server-cache.btm line 142
18:42:58,791 INFO [org.infinispan.eviction.impl.PassivationManagerImpl] (ServerService Thread Pool -- 71) ISPN000030: Passivated 0 entries in 0 milliseconds
18:42:58,791 INFO [stdout] (ServerService Thread Pool -- 22) at org.jboss.byteman.rule.expression.MethodExpression.findMethod(MethodExpression.java:325)
18:42:58,791 INFO [stdout] (ServerService Thread Pool -- 22) at org.jboss.byteman.rule.expression.MethodExpression.typeCheck(MethodExpression.java:188)
18:42:58,791 INFO [stdout] (ServerService Thread Pool -- 22) at org.jboss.byteman.rule.expression.StringPlusExpression.typeCheck(StringPlusExpression.java:52)
18:42:58,791 INFO [stdout] (ServerService Thread Pool -- 22) at org.jboss.byteman.rule.expression.MethodExpression.findMethod(MethodExpression.java:293)
18:42:58,791 INFO [stdout] (ServerService Thread Pool -- 22) at org.jboss.byteman.rule.expression.MethodExpression.typeCheck(MethodExpression.java:188)
18:42:58,791 INFO [stdout] (ServerService Thread Pool -- 22) at org.jboss.byteman.rule.Action.typeCheck(Action.java:106)
18:42:58,791 INFO [stdout] (ServerService Thread Pool -- 22) at org.jboss.byteman.rule.Rule.typeCheck(Rule.java:523)
18:42:58,791 INFO [stdout] (ServerService Thread Pool -- 22) at org.jboss.byteman.rule.Rule.ensureTypeCheckedCompiled(Rule.java:449)
18:42:58,791 INFO [stdout] (ServerService Thread Pool -- 22) at org.jboss.byteman.rule.Rule.execute(Rule.java:672)
18:42:58,791 INFO [stdout] (ServerService Thread Pool -- 22) at org.jboss.byteman.rule.Rule.execute(Rule.java:653)
18:42:58,791 INFO [stdout] (ServerService Thread Pool -- 22) at org.jboss.as.ejb3.component.stateful.StatefulSessionComponent.destroyInstance(StatefulSessionComponent.java)
18:42:58,791 INFO [stdout] (ServerService Thread Pool -- 22) at org.jboss.as.ejb3.component.stateful.StatefulSessionComponent.destroyInstance(StatefulSessionComponent.java:75)
18:42:58,792 INFO [stdout] (ServerService Thread Pool -- 22) at org.jboss.as.ejb3.cache.simple.SimpleCache.stop(SimpleCache.java:91)
18:42:58,792 INFO [stdout] (ServerService Thread Pool -- 22) at org.jboss.as.ejb3.component.stateful.StatefulSessionComponent.done(StatefulSessionComponent.java:369)
18:42:58,792 INFO [stdout] (ServerService Thread Pool -- 22) at org.jboss.as.ejb3.component.EJBComponent.stop(EJBComponent.java:553)
18:42:58,792 INFO [stdout] (ServerService Thread Pool -- 22) at org.jboss.as.ee.component.ComponentStartService$2.run(ComponentStartService.java:78)
18:42:58,792 INFO [stdout] (ServerService Thread Pool -- 22) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
18:42:58,792 INFO [stdout] (ServerService Thread Pool -- 22) at java.util.concurrent.FutureTask.run(FutureTask.java:266)
18:42:58,792 INFO [stdout] (ServerService Thread Pool -- 22) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
18:42:58,792 INFO [stdout] (ServerService Thread Pool -- 22) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
18:42:58,792 INFO [stdout] (ServerService Thread Pool -- 22) at java.lang.Thread.run(Thread.java:745)
18:42:58,792 INFO [stdout] (ServerService Thread Pool -- 22) at org.jboss.threads.JBossThread.run(JBossThread.java:320)
18:42:58,792 INFO [stdout] (ServerService Thread Pool -- 22)
18:42:58,792 INFO [stdout] (ServerService Thread Pool -- 22) Rule.execute called for StatefulSessionComponentInstance_setRemoved_10
18:42:58,794 INFO [org.jboss.as.clustering.infinispan] (ServerService Thread Pool -- 18) WFLYCLINF0003: Stopped stateful-failover.war cache from web container
18:42:58,794 INFO [stdout] (ServerService Thread Pool -- 22) HelperManager.install for helper class org.jboss.byteman.rule.helper.Helper
18:42:58,794 INFO [stdout] (ServerService Thread Pool -- 22) calling installed(StatefulSessionComponentInstance_setRemoved) for helper classorg.jboss.byteman.rule.helper.Helper
18:42:58,794 INFO [stdout] (ServerService Thread Pool -- 22) Installed rule using default helper : StatefulSessionComponentInstance_setRemoved
18:42:58,794 INFO [stdout] (ServerService Thread Pool -- 22) StatefulSessionComponentInstance_setRemoved execute
18:42:58,794 INFO [stdout] (ServerService Thread Pool -- 22) [BYTEMAN-StatefulSessionComponentInstance] setRemoved, sessionID: UnknownSessionID [7050545754535765525152575252684957525555507054695450535565534953]
18:42:58,794 INFO [stdout] (ServerService Thread Pool -- 22) Rule.execute called for StatefulSessionComponent_destroyInstance_1
18:42:58,795 INFO [stdout] (ServerService Thread Pool -- 22) Rule.execute called for StatefulSessionComponentInstance_setRemoved_10
18:42:58,795 INFO [stdout] (ServerService Thread Pool -- 22) StatefulSessionComponentInstance_setRemoved execute
This occurs with or without the package name on the method parameter class.
-
9. Re: problems with org.jboss.as package names in Wildfly
jameslivingston Jan 27, 2016 7:24 PM (in response to rachmato)That's just the same problem in a different form.
StatefulSessionComponentInstance has the method "SessionID getId()", which is the implementation of Identifiable's "K getId()" where K is fixed to SessionID. The Java compiler inserts a synthetic bridge "Object getId() { return getId(); }" calling the one that returns SessionID. Java does not let you directly write methods overloaded purely on the return type, and I believe (but are not sure) that if there is only one non-bridge method it assumes that they all point to it, so it does not warn about the ambiguity.
ByteMan's MethodExpression.findMethod() and bestMatchCandidate() have logic for determining which one should be used, and that error is printed when it return multiple candidates. The current code only looks at the argument types, not return types. To handle covariant return types, I think it would need to be changed so that if there are multiple candidates with identical arguments, then it checks whether there is one which is strictly more specific than the others. I don't think there is JIRA issue for that yet.
adinn does that sound right?
-
10. Re: problems with org.jboss.as package names in Wildfly
adinn Jan 28, 2016 6:14 AM (in response to jameslivingston)Hi James/Richard,
James' first post is correct in what it says about the compiler inserting bridge methods. This occurs when you have a class which implements a specific instantiation of a template class. However, the rest of that first account does not correctly diagnose the problem in the corresponding (first) example.
The ambiguity there is not to do with the target method destroyInstance. Byteman does not attempt to inject into synthetic methods (look at TransformContext.matchTargetMethod to see where this check happens). So we can be sure that the type check is indeed being performed for the rule injected into the version of the method with signature destroyInstance(StatefulSessionComponentInstance).
So, let's move on to the error itself. If you look at the stack trace and error message in the first example you can see that the ambiguity occurs when type-checking the call to getId() in the BIND clause.
. . . 14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) org.jboss.byteman.rule.exception.TypeException: MethodExpression.typeCheck : ambiguous method signature getId for target class org.jboss.as.ejb3.component.stateful.StatefulSessionComponentInstance file /home/nrla/byteman-scripts/script-server-cache.btm line 140 14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.byteman.rule.expression.MethodExpression.findMethod(MethodExpression.java:325) 14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.byteman.rule.expression.MethodExpression.typeCheck(MethodExpression.java:188) 14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.byteman.rule.binding.Binding.typeCheck(Binding.java:131) 14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.byteman.rule.Event.typeCheck(Event.java:114) 14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.byteman.rule.Event.typeCheck(Event.java:106) 14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.byteman.rule.Rule.typeCheck(Rule.java:521) 14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.byteman.rule.Rule.ensureTypeCheckedCompiled(Rule.java:449) 14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.byteman.rule.Rule.execute(Rule.java:672) 14:45:42,226 INFO [stdout] (ServerService Thread Pool -- 17) at org.jboss.byteman.rule.Rule.execute(Rule.java:653) . . .
The type check is looking for a method with no arguments. You might expect it to use the variable type declaration to impose the additional constraint that the return type has to be String.However, since the method expression is being used as a BIND var initializer that is not the full story.
Byteman typechecks an initializer expression X:T = M(E,.1..En) by type checking the expression M(E1,..En) with an unconstrained return type (it passes expected tupe = Unknown to the typeCheck call). If the type checker can derive a unique method from the method name and the types of the input expressions it then goes on to check the return type R to ensure
1) R == T or 2) R < T or 3) T < R where C1 < C2 indicates that C1 extends C2 OR C1 implements C2.
It also allows three other cases to support type inference
4) R == Numeric/Object AND T is primitive or 5) R is primitive and T is Numeric or 6) R == String
in which case(s) Byteman's type inferrer is willing either to box/unbox a number or Stringify an object by inserting a toString call.
The surprising case is the 3rd one. It is included because Byteman is willing to downcast expressions in initializer expressions i.e. if a method M(x1,...xn) returns an Object then Byteman is willing to assign it to a BIND variable X of type String. If it returns a Foo then Byteman will assign to a variable of type FooBar extends Foo. Of course Byteman also inserts a checkcast which will generate a runtime exception if the assignment is invalid.
Ironically, downcasting was introduced explicitly to allow generic data from template classes to be accessed using the template type rather than as generic objects. e.g. if a template type X<T> has a field f of type <T> which is actually stored as an Object then Byteman will allow you to write BIND s:String = x1.f which is fine (modulo a checkcast) if you know that x1 is an instance of X<String>.
What is happening here is that the type check for the getId call is encountering two version of getId(), a synthetic one which returns an Object and a non-synthetic one which returns a String.Two versions exist because the class in question implements an instantiated template; the implementation method which returns a String has to be wrapped with a generic method which returns an Object. Since the check cannot use the downcast type to select the desired implementation the call is ambiguous.
I'll need to think about whether this can be fixed. A simple fix is to special case and push the BIND var type as an expected type when the intiializer is a method expression. That would ensure that when a String is required the method returning a String is picked (it would still leave things ambiguous if the bind var type was Object). Indeed, there is a precedent for special casing. I already special case iniitalizer type checks when the initializer is an array literal as in, say o:Object[] = like {1, 2, 3} . This type strictness is needed because although you could legitimately create an int[] and assign it to an Object[] you risk getting a type error if the rule subsequently tries to assign the int[] e.g. DO o[0] = "hello".
However, special-casing is really only a sticking-plaster solution. Not only does it merely deal with one side of initializer problem (only fixing the case where the bind vartype is the subtype) it also fails to deal with manifestations of the same problem in other contexts. Assume that we have an expression like x.m().name anywhere in the rule and that we infer that the field expression has type F and that expression x has type X. Knowing F and X does not help to select the method return type R. Once we identify a method m then we can check whether R has a field name of type F. But if X has both a synthetic implementation of m with type T1 and a non-synthetic implementation with type T2 extends T1 we are still left with an ambiguous method type irrespective of the fact that we know both input and return types for the original expression.
Another tack which looks like an option is to ignore the synthetic method. However, I am not sure that is actually the correct move either. Since application code can legitimately access at the object level who is ot say that the rule is not intended to access at the same level. I'll need to think further before making a decision on this point.
-
11. Re: problems with org.jboss.as package names in Wildfly
rachmato Jan 28, 2016 8:27 AM (in response to adinn)Hi James/Andrew
FYI, if I remove the bind clause completely, leaving the rule thus:
RULE StatefulSessionComponent_destroyInstance CLASS org.jboss.as.ejb3.component.stateful.StatefulSessionComponent METHOD destroyInstance(StatefulSessionComponentInstance) #BIND # appName:String = "<" + $this.getApplicationName() + "." + $this.getModuleName() + "." + $this.getDistinctName() + ">"; AT ENTRY IF TRUE DO System.out.println("[BYTEMAN-StatefulSessionComponent] destroy instance, id: " + $1.getId()) ENDRULE
I see this error appearing in the logs:
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) Rule.ensureTypeCheckedCompiled : error type checking rule StatefulSessionComponent_destroyInstance
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) org.jboss.byteman.rule.exception.TypeException: MethodExpression.typeCheck : ambiguous method signature getId for target class org.jboss.as.ejb3.component.stateful.StatefulSessionComponentInstance file /home/nrla/byteman-scripts/script-server-cache.btm line 145
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at org.jboss.byteman.rule.expression.MethodExpression.findMethod(MethodExpression.java:325)
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at org.jboss.byteman.rule.expression.MethodExpression.typeCheck(MethodExpression.java:188)
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at org.jboss.byteman.rule.expression.StringPlusExpression.typeCheck(StringPlusExpression.java:52)
m08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at org.jboss.byteman.rule.expression.MethodExpression.findMethod(MethodExpression.java:293)
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at org.jboss.byteman.rule.expression.MethodExpression.typeCheck(MethodExpression.java:188)
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at org.jboss.byteman.rule.Action.typeCheck(Action.java:106)
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at org.jboss.byteman.rule.Rule.typeCheck(Rule.java:523)
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at org.jboss.byteman.rule.Rule.ensureTypeCheckedCompiled(Rule.java:449)
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at org.jboss.byteman.rule.Rule.execute(Rule.java:672)
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at org.jboss.byteman.rule.Rule.execute(Rule.java:653)
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at org.jboss.as.ejb3.component.stateful.StatefulSessionComponent.destroyInstance(StatefulSessionComponent.java)
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at org.jboss.as.ejb3.component.stateful.StatefulSessionComponent.destroyInstance(StatefulSessionComponent.java:75)
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at org.jboss.as.ejb3.cache.simple.SimpleCache.stop(SimpleCache.java:91)
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at org.jboss.as.ejb3.component.stateful.StatefulSessionComponent.done(StatefulSessionComponent.java:369)
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at org.jboss.as.ejb3.component.EJBComponent.stop(EJBComponent.java:553)
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at org.jboss.as.ee.component.ComponentStartService$2.run(ComponentStartService.java:78)
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at java.util.concurrent.FutureTask.run(FutureTask.java:266)
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at java.lang.Thread.run(Thread.java:745)
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20) at org.jboss.threads.JBossThread.run(JBossThread.java:320)
08:17:16,770 INFO [stdout] (ServerService Thread Pool -- 20)
-
12. Re: problems with org.jboss.as package names in Wildfly
adinn Jan 28, 2016 9:14 AM (in response to rachmato)Hi Richard,
FYI, if I remove the bind clause completely, leaving the rule thus:
. . .
I see this error appearing in the logs:
. . .
Hmm, yes, it seems the problem will always occur with the current release even if, as with this example, the expected return type is supplied. The method filtering algorithm currently in uses employs the argument types to filter the set of available methods looking for a candidate implementaion. However, it does not use the return type.
That's something we can and should fix: BYTEMAN-310