Hi all,

Martin W. and myself were running into a rather weird issue in unit tests with 
application composers (in per_jvm) mode only on Mac OSX 26.0.1 - the same tests 
are working fine on Linux CI (Ubuntu).

## Context

In our test context we use a @Configeration properties and the application 
resource definitions of TomEE [1] via a property like this:

---------
p.put(„myResourceDE", "new://Resource?class-name=my.fqdn.MyResource" +
"&constructor=locale, resourceName, useLowerCase");
p.put("myResourceDE.resourceName", 
"classpath:/tlm-common-stopwords_de.properties");
p.put(„myResourceDE.locale", "de");
p.put("myResourceDE.useLowerCase", "true“);
---------

Note: MyResource has multiple ctors with varying arguments, so we have 
signatures like (String, String, Boolean OR Locale, String, Boolean OR Locale, 
Properties, Boolean)
As you can see, we rely on the „constructor“ argument of the resource syntax to 
specify the constructor to be used for creating that resource.

## Problem

On OSX 26.0.1, we’re seeing an intermittent exception:

---------
org.apache.xbean.recipe.ConstructionException: Invalid and non-convertable 
constructor parameter type: name=resourceName, index=1, 
expected=java.util.Properties, actual=java.lang.String

at 
org.apache.xbean.recipe.ObjectRecipe.extractConstructorArgs(ObjectRecipe.java:597)
at org.apache.xbean.recipe.ObjectRecipe.internalCreate(ObjectRecipe.java:278)
at org.apache.xbean.recipe.AbstractRecipe.create(AbstractRecipe.java:96)
at org.apache.xbean.recipe.AbstractRecipe.create(AbstractRecipe.java:61)
at 
org.apache.openejb.assembler.classic.Assembler.doCreateResource(Assembler.java:3181)
at 
org.apache.openejb.assembler.classic.Assembler.createResource(Assembler.java:3016)
at 
org.apache.openejb.assembler.classic.Assembler.buildContainerSystem(Assembler.java:596)
at 
org.apache.openejb.testing.ApplicationComposers.startContainer(ApplicationComposers.java:1481)
---------

So I went ahead and did a debugging session. On OSX, the test case sometime 
passes and most of the time not (regardless of execution: Maven Surefire vs 
IDEA).
The same test passes reliably on Ubuntu.

## Findings

After some debugging, I came up in XBeans ReflectionUtil.findConstructor(…) [2]

This method relies on 

typeClass.getConstructors()
typeClass.getDeclaredConstructors()

However, according to the Javadoc [3], the order of constructors returned by 
these methods is not deterministic.
As a result, the sorted list (ReflectionUtil#L618f ) can differ between JVMs or 
OS environments.
Because TomEE doesn’t provide type arguments to the ObjectRecipe, the code 
simply picks the first 3-arg constructor found — leading to the exception above 
on OSX.

I wasn’t able to reproduce it in a standalone test case in XBeans or TomEE 
(since it relies on the order in which ctors are returned).

## Expectation vs. Behavior

My expectation is that, since we specify parameter names via 
constructor=locale,resourceName,useLowerCase,
those names should be used to select the appropriate constructor - even if the 
parameter types aren’t specified.

However, in XBean, parameter names are only used if parameter types are also 
provided.
And in TomEE, the Assembler doesn’t currently provide type arguments in 
Assembler#prepareRecipe(final ServiceInfo info)[4], so we end up in this 
situation.

## Question

How is the constructor syntax intended to work when a class provides several 
constructors that all have the same number of parameters (and the given 
parameter names aren’t used).

Should the syntax perhaps support specifying parameter types, for example:

---------
p.put("myResourceDE", "new://Resource?class-name=my.fqdn.MyResource" +
"&constructor=locale(java.lang.String),resourceName(java.lang.String),useLowerCase(java.lang.Boolean)");
---------

Any insights or background on how this constructor resolution is designed to 
behave would be greatly appreciated.

Thanks and Gruß
Richard




[1] https://tomee.apache.org/latest/docs/application-resources.html
[2] 
https://github.com/apache/geronimo-xbean/blob/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ReflectionUtil.java#L583
[3] 
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Class.html#getDeclaredConstructors()
[4] 
https://github.com/apache/tomee/blob/main/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java#L3739

Reply via email to