From 61f4baffedcd0d469a0d579f737d7bac2b1351b5 Mon Sep 17 00:00:00 2001 From: Richard Zowalla Date: Sun, 4 Jan 2026 08:56:32 +0100 Subject: [PATCH 01/19] XBean 4.30-SNAPSHOT --- boms/tomee-microprofile/pom.xml | 10 +++++----- boms/tomee-plume/pom.xml | 10 +++++----- boms/tomee-plus/pom.xml | 10 +++++----- boms/tomee-webprofile/pom.xml | 10 +++++----- pom.xml | 2 +- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/boms/tomee-microprofile/pom.xml b/boms/tomee-microprofile/pom.xml index dd0682974d9..d7cbea70ed2 100644 --- a/boms/tomee-microprofile/pom.xml +++ b/boms/tomee-microprofile/pom.xml @@ -919,27 +919,27 @@ org.apache.xbean xbean-asm9-shaded - 4.28 + 4.30-SNAPSHOT org.apache.xbean xbean-bundleutils - 4.28 + 4.30-SNAPSHOT org.apache.xbean xbean-finder-shaded - 4.28 + 4.30-SNAPSHOT org.apache.xbean xbean-naming - 4.28 + 4.30-SNAPSHOT org.apache.xbean xbean-reflect - 4.28 + 4.30-SNAPSHOT org.bitbucket.b_c diff --git a/boms/tomee-plume/pom.xml b/boms/tomee-plume/pom.xml index 061c3dac906..5efd77e2184 100644 --- a/boms/tomee-plume/pom.xml +++ b/boms/tomee-plume/pom.xml @@ -949,27 +949,27 @@ org.apache.xbean xbean-asm9-shaded - 4.28 + 4.30-SNAPSHOT org.apache.xbean xbean-bundleutils - 4.28 + 4.30-SNAPSHOT org.apache.xbean xbean-finder-shaded - 4.28 + 4.30-SNAPSHOT org.apache.xbean xbean-naming - 4.28 + 4.30-SNAPSHOT org.apache.xbean xbean-reflect - 4.28 + 4.30-SNAPSHOT org.bitbucket.b_c diff --git a/boms/tomee-plus/pom.xml b/boms/tomee-plus/pom.xml index 36dfe85a792..982a4ccdaca 100644 --- a/boms/tomee-plus/pom.xml +++ b/boms/tomee-plus/pom.xml @@ -959,27 +959,27 @@ org.apache.xbean xbean-asm9-shaded - 4.28 + 4.30-SNAPSHOT org.apache.xbean xbean-bundleutils - 4.28 + 4.30-SNAPSHOT org.apache.xbean xbean-finder-shaded - 4.28 + 4.30-SNAPSHOT org.apache.xbean xbean-naming - 4.28 + 4.30-SNAPSHOT org.apache.xbean xbean-reflect - 4.28 + 4.30-SNAPSHOT org.bitbucket.b_c diff --git a/boms/tomee-webprofile/pom.xml b/boms/tomee-webprofile/pom.xml index 677f44bab1d..4a222ffe096 100644 --- a/boms/tomee-webprofile/pom.xml +++ b/boms/tomee-webprofile/pom.xml @@ -614,27 +614,27 @@ org.apache.xbean xbean-asm9-shaded - 4.28 + 4.30-SNAPSHOT org.apache.xbean xbean-bundleutils - 4.28 + 4.30-SNAPSHOT org.apache.xbean xbean-finder-shaded - 4.28 + 4.30-SNAPSHOT org.apache.xbean xbean-naming - 4.28 + 4.30-SNAPSHOT org.apache.xbean xbean-reflect - 4.28 + 4.30-SNAPSHOT org.bitbucket.b_c diff --git a/pom.xml b/pom.xml index 4ab44a1bc30..36e1f2b3324 100644 --- a/pom.xml +++ b/pom.xml @@ -135,7 +135,7 @@ 1.2.6 2.5.1 - 4.28 + 4.30-SNAPSHOT 2.4.21 11.0.20 3.11.1 From 8965c3d72175a10ef4ea4dc0f8af065b14033815 Mon Sep 17 00:00:00 2001 From: Richard Zowalla Date: Sun, 4 Jan 2026 12:59:12 +0100 Subject: [PATCH 02/19] Explicitly set the datasource ctor arg types for datasources --- .../org/apache/openejb/assembler/classic/Assembler.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java index 72bf4ca06aa..a7050bb98c1 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java @@ -3153,6 +3153,13 @@ public synchronized boolean containsKey(final Object key) { } } serviceRecipe.setProperty("Definition", PropertiesHelper.propertiesToString(props)); + //explicitly set the argument types to avoid ambiquity in factory resolution. + serviceRecipe.setConstructorArgTypes( + new Class[]{ + String.class, boolean.class, Class.class, String.class, + Duration.class, Duration.class, Duration.class, + boolean.class} + ); } // else: any other kind of resource relying on it? shouldnt be replaceResourceAdapterProperty(serviceRecipe); From 4fe6b643efd9b2d4c1efb7ebcb20adc6758d98e5 Mon Sep 17 00:00:00 2001 From: Richard Zowalla Date: Sun, 4 Jan 2026 13:25:07 +0100 Subject: [PATCH 03/19] Explicitly set the ctor arg types for jms queue --- .../org/apache/openejb/assembler/classic/Assembler.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java index a7050bb98c1..014d20bc6b2 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java @@ -185,6 +185,7 @@ import jakarta.enterprise.inject.spi.BeanManager; import jakarta.enterprise.inject.spi.DefinitionException; import jakarta.enterprise.inject.spi.DeploymentException; +import jakarta.jms.Queue; import javax.management.DynamicMBean; import javax.management.InstanceNotFoundException; import javax.management.MBeanRegistrationException; @@ -3153,7 +3154,7 @@ public synchronized boolean containsKey(final Object key) { } } serviceRecipe.setProperty("Definition", PropertiesHelper.propertiesToString(props)); - //explicitly set the argument types to avoid ambiquity in factory resolution. + //explicitly set the argument types to avoid ambiguity in factory resolution. serviceRecipe.setConstructorArgTypes( new Class[]{ String.class, boolean.class, Class.class, String.class, @@ -3162,6 +3163,11 @@ public synchronized boolean containsKey(final Object key) { ); } // else: any other kind of resource relying on it? shouldnt be + //explicitly set the constructor types to avoid ambiguity in ctor resolution. + if (serviceInfo.types.contains("Queue") || serviceInfo.types.contains(Queue.class.getName())) { + serviceRecipe.setConstructorArgTypes(new Class[]{String.class}); + } + replaceResourceAdapterProperty(serviceRecipe); ClassLoader loader = Thread.currentThread().getContextClassLoader(); From 6d7034aa92ba5d2945dae85a56c4203b87035210 Mon Sep 17 00:00:00 2001 From: Richard Zowalla <13417392+rzo1@users.noreply.github.com> Date: Sun, 4 Jan 2026 17:22:57 +0100 Subject: [PATCH 04/19] Revert explicit declaration of constructor arg types --- .../openejb/assembler/classic/Assembler.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java index 014d20bc6b2..70244de3151 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java @@ -3155,18 +3155,18 @@ public synchronized boolean containsKey(final Object key) { } serviceRecipe.setProperty("Definition", PropertiesHelper.propertiesToString(props)); //explicitly set the argument types to avoid ambiguity in factory resolution. - serviceRecipe.setConstructorArgTypes( - new Class[]{ - String.class, boolean.class, Class.class, String.class, - Duration.class, Duration.class, Duration.class, - boolean.class} +// serviceRecipe.setConstructorArgTypes( +// new Class[]{ +// String.class, boolean.class, Class.class, String.class, +// Duration.class, Duration.class, Duration.class, +// boolean.class} ); } // else: any other kind of resource relying on it? shouldnt be //explicitly set the constructor types to avoid ambiguity in ctor resolution. - if (serviceInfo.types.contains("Queue") || serviceInfo.types.contains(Queue.class.getName())) { - serviceRecipe.setConstructorArgTypes(new Class[]{String.class}); - } +// if (serviceInfo.types.contains("Queue") || serviceInfo.types.contains(Queue.class.getName())) { +// serviceRecipe.setConstructorArgTypes(new Class[]{String.class}); +// } replaceResourceAdapterProperty(serviceRecipe); From 8e6aa49b2e6e8cd1aa8e7ab6f4f7153a531066fa Mon Sep 17 00:00:00 2001 From: Markus Jung Date: Sun, 4 Jan 2026 17:29:10 +0100 Subject: [PATCH 05/19] fix syntax --- .../java/org/apache/openejb/assembler/classic/Assembler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java index 70244de3151..5ec42cd5833 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java @@ -3160,7 +3160,7 @@ public synchronized boolean containsKey(final Object key) { // String.class, boolean.class, Class.class, String.class, // Duration.class, Duration.class, Duration.class, // boolean.class} - ); +// ); } // else: any other kind of resource relying on it? shouldnt be //explicitly set the constructor types to avoid ambiguity in ctor resolution. From 05b9099ee988ea41348d7d8321b911aa7efb7601 Mon Sep 17 00:00:00 2001 From: Markus Jung Date: Sun, 4 Jan 2026 17:55:53 +0100 Subject: [PATCH 06/19] configurable constructor-types for ServiceProvider --- .../openejb/assembler/classic/Assembler.java | 13 ++++++++-- .../assembler/classic/ServiceInfo.java | 1 + .../org/apache/openejb/config/AutoConfig.java | 1 + .../openejb/config/ConfigurationFactory.java | 24 +++++++++++++++---- .../config/provider/ProviderManager.java | 3 +++ .../openejb/config/sys/ServiceProvider.java | 22 +++++++++++++++++ .../src/main/resources/schema/service-jar.xsd | 1 + 7 files changed, 58 insertions(+), 7 deletions(-) diff --git a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java index 5ec42cd5833..15222b83244 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java @@ -261,6 +261,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.ReentrantLock; +import java.util.stream.Collectors; import static org.apache.openejb.util.Classes.ancestors; @@ -1409,6 +1410,13 @@ public static void mergeServices(final AppInfo appInfo) throws URISyntaxExceptio if (si.constructorArgs != null && !si.constructorArgs.isEmpty()) { query.put("constructor", Join.join(",", si.constructorArgs)); } + if (si.constructorArgTypes != null && !si.constructorArgTypes.isEmpty()) { + String rawConstructorArgTypes = si.constructorArgTypes.stream() + .map(Class::getName) + .collect(Collectors.joining(",")); + + query.put("constructor-types", Join.join(",", rawConstructorArgTypes)); + } appInfo.properties.put(si.id, "new://Service?" + URISupport.createQueryString(query)); if (si.properties != null) { for (final String k : si.properties.stringPropertyNames()) { @@ -3750,8 +3758,9 @@ private static void unusedProperty(final String id, final String property) { } public static ObjectRecipe prepareRecipe(final ServiceInfo info) { - final String[] constructorArgs = info.constructorArgs.toArray(new String[info.constructorArgs.size()]); - final ObjectRecipe serviceRecipe = new ObjectRecipe(info.className, info.factoryMethod, constructorArgs, null); + final String[] constructorArgs = info.constructorArgs.toArray(new String[0]); + final Class[] constructorArgTypes = info.constructorArgTypes.toArray(new Class[0]); + final ObjectRecipe serviceRecipe = new ObjectRecipe(info.className, info.factoryMethod, constructorArgs, constructorArgTypes); serviceRecipe.allow(Option.CASE_INSENSITIVE_PROPERTIES); serviceRecipe.allow(Option.IGNORE_MISSING_PROPERTIES); serviceRecipe.allow(Option.PRIVATE_PROPERTIES); diff --git a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ServiceInfo.java b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ServiceInfo.java index 429a134eb2c..619ab0822cb 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ServiceInfo.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ServiceInfo.java @@ -35,6 +35,7 @@ public class ServiceInfo extends InfoObject { public String classpathAPI; public Properties properties; public final List constructorArgs = new ArrayList<>(); + public final List> constructorArgTypes = new ArrayList<>(); public Properties unsetProperties; // keep it in the model to be able to investigate it dumping Infos /** diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/AutoConfig.java b/container/openejb-core/src/main/java/org/apache/openejb/config/AutoConfig.java index c247580bb67..eb3567dd445 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/AutoConfig.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/AutoConfig.java @@ -1922,6 +1922,7 @@ private ResourceInfo copy(final ResourceInfo a) { b.description = a.description; b.factoryMethod = a.factoryMethod; b.constructorArgs.addAll(a.constructorArgs); + b.constructorArgTypes.addAll(a.constructorArgTypes); b.originAppName = a.originAppName; b.types.addAll(a.types); b.properties = new SuperProperties(); diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java b/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java index 0e0f8b6033f..5428f049b85 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java @@ -19,6 +19,7 @@ import org.apache.openejb.Extensions; import org.apache.openejb.OpenEJBException; +import org.apache.openejb.OpenEJBRuntimeException; import org.apache.openejb.Vendor; import org.apache.openejb.api.Proxy; import org.apache.openejb.api.resource.PropertiesResourceProvider; @@ -122,6 +123,7 @@ import java.util.Map; import java.util.Properties; import java.util.Set; +import java.util.stream.Collectors; import static org.apache.openejb.config.DeploymentsResolver.DEPLOYMENTS_CLASSPATH_PROPERTY; import static org.apache.openejb.config.ServiceUtils.implies; @@ -1289,7 +1291,8 @@ public T configureService(org.apache.openejb.config.Serv info.factoryMethod = provider.getFactoryName(); info.id = service.getId(); info.properties = props; - info.constructorArgs.addAll(parseConstructorArgs(provider)); + info.constructorArgs.addAll(parseList(provider.getConstructor())); + info.constructorArgTypes.addAll(parseConstructorArgTypes(provider)); if (info instanceof ResourceInfo && service instanceof Resource) { final ResourceInfo ri = ResourceInfo.class.cast(info); final Resource resource = Resource.class.cast(service); @@ -1598,12 +1601,23 @@ protected static Class getContainerInfoType(final Strin return containerTypes.get(ctype); } - private List parseConstructorArgs(final ServiceProvider service) { - final String constructor = service.getConstructor(); - if (constructor == null) { + private List parseList(final String raw) { + if (raw == null) { return Collections.emptyList(); } - return Arrays.asList(constructor.split("[ ,]+")); + return Arrays.asList(raw.split("[ ,]+")); + } + + private List> parseConstructorArgTypes(final ServiceProvider service) { + return parseList(service.getConstructorTypes()).stream() + .map(it -> { + try { + return Class.forName(it); + } catch (final ClassNotFoundException e) { + throw new OpenEJBRuntimeException(e); + } + }) + .collect(Collectors.toUnmodifiableList()); } protected List getResourceIds() { diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/provider/ProviderManager.java b/container/openejb-core/src/main/java/org/apache/openejb/config/provider/ProviderManager.java index 2f4616900d6..d5885d2da45 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/provider/ProviderManager.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/provider/ProviderManager.java @@ -130,6 +130,9 @@ private void inherit(final ServiceProvider child, final ServiceProvider parent) if (n(child.getConstructor())) { child.setConstructor(parent.getConstructor()); } + if (n(child.getConstructorTypes())) { + child.setConstructor(parent.getConstructorTypes()); + } if (n(child.getFactoryName())) { child.setFactoryName(parent.getFactoryName()); } diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/ServiceProvider.java b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/ServiceProvider.java index 7c92f3adb59..cfcf8a6c71c 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/ServiceProvider.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/ServiceProvider.java @@ -64,6 +64,8 @@ public class ServiceProvider { protected String className; @XmlAttribute(name = "constructor") protected String constructor; + @XmlAttribute(name = "constructor-types") + protected String constructorTypes; @XmlAttribute protected String description; @XmlAttribute(name = "display-name") @@ -162,6 +164,26 @@ public void setConstructor(final String value) { this.constructor = value; } + /** + * Gets the value of the constructorTypes property. + * + * @return possible object is + * {@link String } + */ + public String getConstructorTypes() { + return constructorTypes; + } + + /** + * Sets the value of the constructorTypes property. + * + * @param value allowed object is + * {@link String } + */ + public void setConstructorTypes(final String value) { + this.constructorTypes = value; + } + /** * Gets the value of the description property. * diff --git a/container/openejb-core/src/main/resources/schema/service-jar.xsd b/container/openejb-core/src/main/resources/schema/service-jar.xsd index 232e7a92543..726e16e1a05 100644 --- a/container/openejb-core/src/main/resources/schema/service-jar.xsd +++ b/container/openejb-core/src/main/resources/schema/service-jar.xsd @@ -46,6 +46,7 @@ + From a49bb0df4f28845a16f2a44d58e982771ce77751 Mon Sep 17 00:00:00 2001 From: Richard Zowalla Date: Sun, 4 Jan 2026 20:23:50 +0100 Subject: [PATCH 07/19] Add missing constructor-types parsing --- .../src/main/java/org/apache/openejb/config/sys/JaxbOpenejb.java | 1 + 1 file changed, 1 insertion(+) diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/JaxbOpenejb.java b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/JaxbOpenejb.java index ba7f06779ac..f65cc788c2b 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/JaxbOpenejb.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/JaxbOpenejb.java @@ -481,6 +481,7 @@ public void startElement(final String uri, final String localName, final String provider.setService(att.getValue("", "service")); provider.setFactoryName(att.getValue("", "factory-name")); provider.setConstructor(att.getValue("", "constructor")); + provider.setConstructorTypes(att.getValue("", "constructor-types")); provider.setClassName(att.getValue("", "class-name")); provider.setParent(att.getValue("", "parent")); final String typesString = att.getValue("", "types"); From 9ace2fbf4c5245c3959c4cdaac0c922fe488c024 Mon Sep 17 00:00:00 2001 From: Richard Zowalla Date: Sun, 4 Jan 2026 20:24:24 +0100 Subject: [PATCH 08/19] Implement constructor-types matching for geronimo transaction manager case --- .../openejb/config/ConfigurationFactory.java | 24 ++++++++++++++++++- .../openejb/config/sys/ServiceProvider.java | 1 + .../org.apache.openejb/service-jar.xml | 15 ++++++------ 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java b/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java index 5428f049b85..4f92eb779db 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java @@ -107,6 +107,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.lang.reflect.Array; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; @@ -1612,7 +1613,7 @@ private List> parseConstructorArgTypes(final ServiceProvider service) { return parseList(service.getConstructorTypes()).stream() .map(it -> { try { - return Class.forName(it); + return getClassForType(it); } catch (final ClassNotFoundException e) { throw new OpenEJBRuntimeException(e); } @@ -1620,6 +1621,27 @@ private List> parseConstructorArgTypes(final ServiceProvider service) { .collect(Collectors.toUnmodifiableList()); } + private Class getClassForType(String typeName) throws ClassNotFoundException { + if (typeName.endsWith("[]")) { + final String elementType = typeName.substring(0, typeName.length() - 2); + final Class elementClass = getClassForType(elementType); // recursion + return Array.newInstance(elementClass, 0).getClass(); + } + + return switch (typeName) { + case "boolean" -> boolean.class; + case "byte" -> byte.class; + case "char" -> char.class; + case "short" -> short.class; + case "int" -> int.class; + case "long" -> long.class; + case "float" -> float.class; + case "double" -> double.class; + case "void" -> void.class; + default -> Class.forName(typeName); // regular case + }; + } + protected List getResourceIds() { return getResourceIds(null); } diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/ServiceProvider.java b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/ServiceProvider.java index cfcf8a6c71c..1b2c042298f 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/ServiceProvider.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/ServiceProvider.java @@ -46,6 +46,7 @@ * <attribute name="id" use="required" type="{http://www.w3.org/2001/XMLSchema}string" /> * <attribute name="provider-type" use="required" type="{http://www.openejb.org/Service/Configuration}ProviderTypes" /> * <attribute name="constructor" type="{http://www.w3.org/2001/XMLSchema}string" /> + * <attribute name="constructor-types" type="{http://www.w3.org/2001/XMLSchema}string" /> * <attribute name="factory-name" type="{http://www.w3.org/2001/XMLSchema}string" /> * </extension> * </simpleContent> diff --git a/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml b/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml index 50ef7c58ebf..5a16c882b6c 100644 --- a/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml +++ b/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml @@ -125,7 +125,7 @@ # side of the pool reaches its `MaxAge`, it is also immediately # replaced. Replacement is done in a background queue using the # number of threads specified by `CallbackThreads`. - + MinSize = 0 # StrictPooling tells the container what to do when the pool @@ -362,7 +362,7 @@ # annotation is used. AccessTimeout = 30 seconds - + @@ -428,10 +428,10 @@ # override this setting for the bean where the annotation is used. TimeOut 20 - - # Specifies the frequency (in seconds) at which the bean cache is checked for + + # Specifies the frequency (in seconds) at which the bean cache is checked for # idle beans. - + Frequency 60 # Specifies the size of the bean pools for this @@ -510,8 +510,8 @@ service="SecurityService" types="SecurityService" class-name="org.apache.openejb.core.security.SecurityServiceImpl"> - - DefaultUser guest + + DefaultUser guest defaultTransactionTimeout 10 minutes From aee1041569f435fac20cf6e2cf36c9135d06d96d Mon Sep 17 00:00:00 2001 From: Richard Zowalla Date: Sun, 4 Jan 2026 20:32:44 +0100 Subject: [PATCH 09/19] Additional change to restore previous implicit behaviour if arg types are NOT set --- .../java/org/apache/openejb/assembler/classic/Assembler.java | 3 ++- .../main/resources/META-INF/org.apache.openejb/service-jar.xml | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java index 15222b83244..7a38e87f2a5 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java @@ -3760,7 +3760,8 @@ private static void unusedProperty(final String id, final String property) { public static ObjectRecipe prepareRecipe(final ServiceInfo info) { final String[] constructorArgs = info.constructorArgs.toArray(new String[0]); final Class[] constructorArgTypes = info.constructorArgTypes.toArray(new Class[0]); - final ObjectRecipe serviceRecipe = new ObjectRecipe(info.className, info.factoryMethod, constructorArgs, constructorArgTypes); + final ObjectRecipe serviceRecipe = new ObjectRecipe(info.className, info.factoryMethod, + constructorArgs, constructorArgTypes.length > 0 ? constructorArgTypes : null); //if empty, treat as not set serviceRecipe.allow(Option.CASE_INSENSITIVE_PROPERTIES); serviceRecipe.allow(Option.IGNORE_MISSING_PROPERTIES); serviceRecipe.allow(Option.PRIVATE_PROPERTIES); diff --git a/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml b/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml index 5a16c882b6c..2389edfc88d 100644 --- a/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml +++ b/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml @@ -586,6 +586,7 @@ types="javax.sql.DataSource, DataSource" factory-name="create" constructor="ServiceId, JtaManaged, JdbcDriver, Definition, MaxWaitTime, TimeBetweenEvictionRuns, MinEvictableIdleTime, OpenEJBResourceClasspath" + constructor-types="java.lang.String,boolean,java.lang.Class,java.lang.String,org.apache.openejb.util.Duration,org.apache.openejb.util.Duration,org.apache.openejb.util.Duration,boolean" class-name="org.apache.openejb.resource.jdbc.DataSourceFactory"> # Determines wether or not this data source should be JTA managed # or user managed. If set to 'true' it will automatically be enrolled @@ -707,6 +708,7 @@ service="Resource" types="jakarta.jms.Queue, Queue, jakarta.jms.Destination" constructor="destination" + constructor-types="java.lang.String" class-name="org.apache.activemq.command.ActiveMQQueue"> # Specifies the name of the queue From 0fb2890bcf3e07b14cd4fca9e5fe21e0a1f06351 Mon Sep 17 00:00:00 2001 From: Richard Zowalla Date: Sun, 4 Jan 2026 20:51:31 +0100 Subject: [PATCH 10/19] Add types for unmanaged datasource --- .../main/resources/META-INF/org.apache.openejb/service-jar.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml b/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml index 2389edfc88d..991ecf5b7c9 100644 --- a/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml +++ b/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml @@ -628,6 +628,7 @@ types="javax.sql.DataSource, DataSource" factory-name="create" constructor="ServiceId, JtaManaged, JdbcDriver, Definition, MaxWaitTime, TimeBetweenEvictionRuns, MinEvictableIdleTime, OpenEJBResourceClasspath" + constructor-types="java.lang.String,boolean,java.lang.Class,java.lang.String,org.apache.openejb.util.Duration,org.apache.openejb.util.Duration,org.apache.openejb.util.Duration,boolean" class-name="org.apache.openejb.resource.jdbc.DataSourceFactory"> JtaManaged = false From a0da28f620637bb176fa1eac5c56d5e8fc0cf065 Mon Sep 17 00:00:00 2001 From: Markus Jung Date: Sun, 4 Jan 2026 21:02:42 +0100 Subject: [PATCH 11/19] define constructor arg types where arg name selection was used before --- .../resources/META-INF/org.apache.openejb/service-jar.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml b/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml index 991ecf5b7c9..1a44c9b6605 100644 --- a/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml +++ b/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml @@ -46,6 +46,7 @@ service="Container" types="CMP_ENTITY" constructor="id, transactionManager, securityService, CmpEngineFactory" + constructor-types="java.lang.Object, jakarta.transaction.TransactionManager, org.apache.openejb.spi.SecurityService, java.lang.String" class-name="org.apache.openejb.core.cmp.CmpContainer"> CmpEngineFactory org.apache.openejb.core.cmp.jpa.JpaCmpEngineFactory @@ -61,6 +62,7 @@ service="Container" types="BMP_ENTITY" constructor="id, securityService, PoolSize" + constructor-types="java.lang.Object, org.apache.openejb.spi.SecurityService, int" class-name="org.apache.openejb.core.entity.EntityContainer"> # Specifies the size of the bean pools for this @@ -345,6 +347,7 @@ service="Container" types="SINGLETON" constructor="id, securityService" + constructor-types="java.lang.Object, org.apache.openejb.spi.SecurityService" class-name="org.apache.openejb.core.singleton.SingletonContainer"> # Specifies the maximum time an invocation could wait for the @@ -456,6 +459,7 @@ service="Container" types="MANAGED" constructor="id, securityService" + constructor-types="java.lang.Object, org.apache.openejb.spi.SecurityService" class-name="org.apache.openejb.core.managed.ManagedContainer"> @@ -722,6 +726,7 @@ service="Resource" types="jakarta.jms.Topic, Topic, jakarta.jms.Destination" constructor="destination" + constructor-types="java.lang.String" class-name="org.apache.activemq.command.ActiveMQTopic"> # Specifies the name of the topic From af473d8f64f502578111948ba346610a1291ba76 Mon Sep 17 00:00:00 2001 From: Markus Jung Date: Mon, 5 Jan 2026 14:21:14 +0100 Subject: [PATCH 12/19] Don't store complex class type in ServiceInfo documented in OpenEjbConfigurationValidationTest --- .../openejb/assembler/classic/Assembler.java | 39 ++++++++++++++++--- .../assembler/classic/ServiceInfo.java | 2 +- .../openejb/config/ConfigurationFactory.java | 35 +---------------- 3 files changed, 35 insertions(+), 41 deletions(-) diff --git a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java index 7a38e87f2a5..5be7d978db6 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java @@ -228,6 +228,7 @@ import java.lang.instrument.Instrumentation; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; +import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Proxy; @@ -1411,11 +1412,7 @@ public static void mergeServices(final AppInfo appInfo) throws URISyntaxExceptio query.put("constructor", Join.join(",", si.constructorArgs)); } if (si.constructorArgTypes != null && !si.constructorArgTypes.isEmpty()) { - String rawConstructorArgTypes = si.constructorArgTypes.stream() - .map(Class::getName) - .collect(Collectors.joining(",")); - - query.put("constructor-types", Join.join(",", rawConstructorArgTypes)); + query.put("constructor-types", Join.join(",", si.constructorArgTypes)); } appInfo.properties.put(si.id, "new://Service?" + URISupport.createQueryString(query)); if (si.properties != null) { @@ -3759,7 +3756,16 @@ private static void unusedProperty(final String id, final String property) { public static ObjectRecipe prepareRecipe(final ServiceInfo info) { final String[] constructorArgs = info.constructorArgs.toArray(new String[0]); - final Class[] constructorArgTypes = info.constructorArgTypes.toArray(new Class[0]); + final Class[] constructorArgTypes = info.constructorArgTypes.stream() + .map(it -> { + try { + return getClassForType(it); + } catch (final ClassNotFoundException e) { + throw new OpenEJBRuntimeException(e); + } + }) + .toArray(Class[]::new); + final ObjectRecipe serviceRecipe = new ObjectRecipe(info.className, info.factoryMethod, constructorArgs, constructorArgTypes.length > 0 ? constructorArgTypes : null); //if empty, treat as not set serviceRecipe.allow(Option.CASE_INSENSITIVE_PROPERTIES); @@ -3818,6 +3824,27 @@ private URL toUrl(final String jarPath) throws OpenEJBException { } } + private static Class getClassForType(String typeName) throws ClassNotFoundException { + if (typeName.endsWith("[]")) { + final String elementType = typeName.substring(0, typeName.length() - 2); + final Class elementClass = getClassForType(elementType); // recursion + return Array.newInstance(elementClass, 0).getClass(); + } + + return switch (typeName) { + case "boolean" -> boolean.class; + case "byte" -> byte.class; + case "char" -> char.class; + case "short" -> short.class; + case "int" -> int.class; + case "long" -> long.class; + case "float" -> float.class; + case "double" -> double.class; + case "void" -> void.class; + default -> Class.forName(typeName); // regular case + }; + } + private static class PersistenceClassLoaderHandlerImpl implements PersistenceClassLoaderHandler { private static final AtomicBoolean logged = new AtomicBoolean(false); diff --git a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ServiceInfo.java b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ServiceInfo.java index 619ab0822cb..cde31d962fc 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ServiceInfo.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ServiceInfo.java @@ -35,7 +35,7 @@ public class ServiceInfo extends InfoObject { public String classpathAPI; public Properties properties; public final List constructorArgs = new ArrayList<>(); - public final List> constructorArgTypes = new ArrayList<>(); + public final List constructorArgTypes = new ArrayList<>(); public Properties unsetProperties; // keep it in the model to be able to investigate it dumping Infos /** diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java b/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java index 4f92eb779db..dd3383cc8ed 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java @@ -1293,7 +1293,7 @@ public T configureService(org.apache.openejb.config.Serv info.id = service.getId(); info.properties = props; info.constructorArgs.addAll(parseList(provider.getConstructor())); - info.constructorArgTypes.addAll(parseConstructorArgTypes(provider)); + info.constructorArgTypes.addAll(parseList(provider.getConstructorTypes())); if (info instanceof ResourceInfo && service instanceof Resource) { final ResourceInfo ri = ResourceInfo.class.cast(info); final Resource resource = Resource.class.cast(service); @@ -1609,39 +1609,6 @@ private List parseList(final String raw) { return Arrays.asList(raw.split("[ ,]+")); } - private List> parseConstructorArgTypes(final ServiceProvider service) { - return parseList(service.getConstructorTypes()).stream() - .map(it -> { - try { - return getClassForType(it); - } catch (final ClassNotFoundException e) { - throw new OpenEJBRuntimeException(e); - } - }) - .collect(Collectors.toUnmodifiableList()); - } - - private Class getClassForType(String typeName) throws ClassNotFoundException { - if (typeName.endsWith("[]")) { - final String elementType = typeName.substring(0, typeName.length() - 2); - final Class elementClass = getClassForType(elementType); // recursion - return Array.newInstance(elementClass, 0).getClass(); - } - - return switch (typeName) { - case "boolean" -> boolean.class; - case "byte" -> byte.class; - case "char" -> char.class; - case "short" -> short.class; - case "int" -> int.class; - case "long" -> long.class; - case "float" -> float.class; - case "double" -> double.class; - case "void" -> void.class; - default -> Class.forName(typeName); // regular case - }; - } - protected List getResourceIds() { return getResourceIds(null); } From 87e5ee3de70069c78fe245a49ac00bde5e4f6b11 Mon Sep 17 00:00:00 2001 From: Markus Jung Date: Mon, 5 Jan 2026 14:53:36 +0100 Subject: [PATCH 13/19] support constructor-types for uri definitions and xml --- .../apache/openejb/config/ConfigurationFactory.java | 2 ++ .../main/java/org/apache/openejb/config/Service.java | 2 ++ .../openejb/config/provider/ProviderManager.java | 2 +- .../apache/openejb/config/sys/AbstractService.java | 12 ++++++++++++ .../org/apache/openejb/config/sys/StackHandler.java | 3 +++ .../config/typed/BmpEntityContainerBuilder.java | 1 + .../config/typed/CmpEntityContainerBuilder.java | 2 ++ .../openejb/config/typed/DataSourceBuilder.java | 2 ++ .../config/typed/ManagedContainerBuilder.java | 1 + .../config/typed/MessageDrivenContainerBuilder.java | 1 + .../apache/openejb/config/typed/QueueBuilder.java | 1 + .../config/typed/SingletonContainerBuilder.java | 1 + .../apache/openejb/config/typed/TopicBuilder.java | 1 + .../config/typed/TransactionManagerBuilder.java | 1 + 14 files changed, 31 insertions(+), 1 deletion(-) diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java b/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java index dd3383cc8ed..1f8f0d85acb 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java @@ -797,6 +797,7 @@ public static Object toConfigDeclaration(final String id, final URI uri) throws service.setProvider(map.remove("provider")); service.setClassName(map.remove("class-name")); service.setConstructor(map.remove("constructor")); + service.setConstructorArgTypes(map.remove("constructor-types")); service.setFactoryName(map.remove("factory-name")); service.setPropertiesProvider(map.remove("properties-provider")); service.setTemplate(map.remove("template")); @@ -1462,6 +1463,7 @@ private ServiceProvider resolveServiceProvider(final org.apache.openejb.config.S provider.getTypes().add(service.getType()); provider.setClassName(service.getClassName()); provider.setConstructor(service.getConstructor()); + provider.setConstructorTypes(service.getConstructorArgTypes()); provider.setFactoryName(service.getFactoryName()); return provider; } diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/Service.java b/container/openejb-core/src/main/java/org/apache/openejb/config/Service.java index 370096ef3b7..5d0b8a7ab9d 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/Service.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/Service.java @@ -60,6 +60,8 @@ public interface Service { String getConstructor(); + String getConstructorArgTypes(); + String getFactoryName(); void setClasspath(String classpath); diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/provider/ProviderManager.java b/container/openejb-core/src/main/java/org/apache/openejb/config/provider/ProviderManager.java index d5885d2da45..b4e3f37f488 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/provider/ProviderManager.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/provider/ProviderManager.java @@ -131,7 +131,7 @@ private void inherit(final ServiceProvider child, final ServiceProvider parent) child.setConstructor(parent.getConstructor()); } if (n(child.getConstructorTypes())) { - child.setConstructor(parent.getConstructorTypes()); + child.setConstructorTypes(parent.getConstructorTypes()); } if (n(child.getFactoryName())) { child.setFactoryName(parent.getFactoryName()); diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/AbstractService.java b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/AbstractService.java index b2b42cafd0c..0522a7e6d7d 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/AbstractService.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/AbstractService.java @@ -83,6 +83,9 @@ public abstract class AbstractService implements Service { @XmlAttribute(name = "constructor") protected String constructor; + @XmlAttribute(name = "constructor-types") + protected String constructorArgTypes; + /** * Mutually exclusive with 'provider' */ @@ -231,6 +234,15 @@ public void setConstructor(final String constructor) { this.constructor = constructor; } + @Override + public String getConstructorArgTypes() { + return constructorArgTypes; + } + + public void setConstructorArgTypes(String constructorArgTypes) { + this.constructorArgTypes = constructorArgTypes; + } + public String getFactoryName() { return factoryName; } diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/StackHandler.java b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/StackHandler.java index 4cc1db8ea1f..694bc97bbe3 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/StackHandler.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/StackHandler.java @@ -177,6 +177,9 @@ public void startElement(final String uri, final String localName, final String if (attributes.getValue("constructor") != null) { service.setConstructor(attributes.getValue("constructor")); } + if (attributes.getValue("constructor-types") != null) { + service.setConstructorArgTypes(attributes.getValue("constructor-types")); + } if (attributes.getValue("factory-name") != null) { service.setFactoryName(attributes.getValue("factory-name")); } diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/typed/BmpEntityContainerBuilder.java b/container/openejb-core/src/main/java/org/apache/openejb/config/typed/BmpEntityContainerBuilder.java index 4df9ccf9393..66f70cd6d62 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/typed/BmpEntityContainerBuilder.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/typed/BmpEntityContainerBuilder.java @@ -39,6 +39,7 @@ public BmpEntityContainerBuilder() { setId("BmpEntityContainer"); setConstructor("id, securityService, poolSize"); + setConstructorArgTypes("java.lang.Object, org.apache.openejb.spi.SecurityService, int"); } diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/typed/CmpEntityContainerBuilder.java b/container/openejb-core/src/main/java/org/apache/openejb/config/typed/CmpEntityContainerBuilder.java index 53d2d907a1a..dd94abac928 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/typed/CmpEntityContainerBuilder.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/typed/CmpEntityContainerBuilder.java @@ -39,6 +39,8 @@ public CmpEntityContainerBuilder() { setId("CmpEntityContainer"); setConstructor("id, transactionManager, securityService, cmpEngineFactory"); + setConstructorArgTypes("java.lang.Object, jakarta.transaction.TransactionManager, org.apache.openejb.spi.SecurityService, java.lang.String"); + } diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/typed/DataSourceBuilder.java b/container/openejb-core/src/main/java/org/apache/openejb/config/typed/DataSourceBuilder.java index 60ab3599c2f..5a2a93f1c34 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/typed/DataSourceBuilder.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/typed/DataSourceBuilder.java @@ -99,6 +99,8 @@ public DataSourceBuilder() { setId("DataSource"); setConstructor("serviceId, jtaManaged, jdbcDriver, definition, maxWaitTime, timeBetweenEvictionRuns, minEvictableIdleTime, OpenEJBResourceClasspath"); + setConstructorArgTypes("java.lang.String,boolean,java.lang.Class,java.lang.String,org.apache.openejb.util.Duration,org.apache.openejb.util.Duration,org.apache.openejb.util.Duration,boolean"); + setFactoryName("create"); diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/typed/ManagedContainerBuilder.java b/container/openejb-core/src/main/java/org/apache/openejb/config/typed/ManagedContainerBuilder.java index ac5177c7064..3aa40d183d2 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/typed/ManagedContainerBuilder.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/typed/ManagedContainerBuilder.java @@ -36,6 +36,7 @@ public ManagedContainerBuilder() { setId("ManagedContainer"); setConstructor("id, securityService"); + setConstructorArgTypes("java.lang.Object, org.apache.openejb.spi.SecurityService"); } diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/typed/MessageDrivenContainerBuilder.java b/container/openejb-core/src/main/java/org/apache/openejb/config/typed/MessageDrivenContainerBuilder.java index 94721f98112..123e75e64d0 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/typed/MessageDrivenContainerBuilder.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/typed/MessageDrivenContainerBuilder.java @@ -45,6 +45,7 @@ public MessageDrivenContainerBuilder() { setId("MessageDrivenContainer"); setConstructor("id, securityService, resourceAdapter, messageListenerInterface, activationSpecClass, instanceLimit, failOnUnknownActivationSpec"); + setConstructorArgTypes("java.lang.Object, org.apache.openejb.spi.SecurityService, jakarta.resource.spi.ResourceAdapter, java.lang.Class, java.langClass, int, boolean"); } diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/typed/QueueBuilder.java b/container/openejb-core/src/main/java/org/apache/openejb/config/typed/QueueBuilder.java index d163cc0324e..538be302a0f 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/typed/QueueBuilder.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/typed/QueueBuilder.java @@ -39,6 +39,7 @@ public QueueBuilder() { setId("Queue"); setConstructor("destination"); + setConstructorArgTypes("java.lang.String"); } diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/typed/SingletonContainerBuilder.java b/container/openejb-core/src/main/java/org/apache/openejb/config/typed/SingletonContainerBuilder.java index 9a9d660a89b..634f7e4af4c 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/typed/SingletonContainerBuilder.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/typed/SingletonContainerBuilder.java @@ -44,6 +44,7 @@ public SingletonContainerBuilder() { setId("SingletonContainer"); setConstructor("id, securityService"); + setConstructorArgTypes("java.lang.Object, org.apache.openejb.spi.SecurityService"); } diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/typed/TopicBuilder.java b/container/openejb-core/src/main/java/org/apache/openejb/config/typed/TopicBuilder.java index 854bf79492b..fc8b0aeaf75 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/typed/TopicBuilder.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/typed/TopicBuilder.java @@ -39,6 +39,7 @@ public TopicBuilder() { setId("Topic"); setConstructor("destination"); + setConstructorArgTypes("java.lang.String"); } diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/typed/TransactionManagerBuilder.java b/container/openejb-core/src/main/java/org/apache/openejb/config/typed/TransactionManagerBuilder.java index f7296c5beaf..e03dea04fc7 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/typed/TransactionManagerBuilder.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/typed/TransactionManagerBuilder.java @@ -71,6 +71,7 @@ public TransactionManagerBuilder() { setId("TransactionManager"); setConstructor("defaultTransactionTimeoutSeconds, defaultTransactionTimeout, txRecovery, tmId, bufferClassName, bufferSizeKb, checksumEnabled, adler32Checksum, flushSleepTimeMilliseconds, flushSleepTime, logFileDir, logFileExt, logFileName, maxBlocksPerFile, maxBuffers, maxLogFiles, minBuffers, threadsWaitingForceThreshold"); + setConstructorArgTypes("java.lang.Integer, org.apache.openejb.util.Duration, boolean, byte[], java.lang.String, int, boolean, boolean, java.lang.Integer, org.apache.openejb.util.Duration, java.lang.String, java.lang.String, java.lang.String, int, int, int, int, int"); setFactoryName("create"); From 6c8cca56dda45d5c506a513e319d8f373d752dd3 Mon Sep 17 00:00:00 2001 From: Markus Jung Date: Mon, 5 Jan 2026 15:20:50 +0100 Subject: [PATCH 14/19] fix URLAsResourceTest --- .../java/org/apache/openejb/resource/URLAsResourceTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/openejb-core/src/test/java/org/apache/openejb/resource/URLAsResourceTest.java b/container/openejb-core/src/test/java/org/apache/openejb/resource/URLAsResourceTest.java index 0e5aa786115..e8496add81d 100644 --- a/container/openejb-core/src/test/java/org/apache/openejb/resource/URLAsResourceTest.java +++ b/container/openejb-core/src/test/java/org/apache/openejb/resource/URLAsResourceTest.java @@ -39,7 +39,7 @@ public class URLAsResourceTest { @Configuration public Properties config() { return new PropertiesBuilder() - .p("url", "new://Resource?class-name=java.net.URL&constructor=value") + .p("url", "new://Resource?class-name=java.net.URL&constructor=value&constructor-types=java.lang.String") .p("url.value", "http://tomee.apache.org") .build(); } From e086531d31a4ec0862bd3d7f97c25c7e9980327c Mon Sep 17 00:00:00 2001 From: Richard Zowalla Date: Mon, 5 Jan 2026 19:29:24 +0100 Subject: [PATCH 15/19] Update documentation --- docs/admin/configuration/application.adoc | 2 +- docs/application-resources.adoc | 19 + docs/containers-and-resources.adoc | 586 ++++++++++------------ 3 files changed, 285 insertions(+), 322 deletions(-) diff --git a/docs/admin/configuration/application.adoc b/docs/admin/configuration/application.adoc index 775492e1a03..a91ba38a208 100644 --- a/docs/admin/configuration/application.adoc +++ b/docs/admin/configuration/application.adoc @@ -87,7 +87,7 @@ to use a MySQL database on OpenShift you can do: `resources.xml` supports `Resource`, `Service` and `Container`. -=== `resources.xml` mecanism +=== `resources.xml` mechanism `resources.xml` resources are still available globally like any `tomee.xml` resource. diff --git a/docs/application-resources.adoc b/docs/application-resources.adoc index 8620ac11240..21f04e59036 100644 --- a/docs/application-resources.adoc +++ b/docs/application-resources.adoc @@ -290,6 +290,25 @@ specify the arguments as a comma separated list: ---- +=== constructor-types + +When no types are explicitly defined, the underlying mechanism relies on implicit matching to bind +the declared properties to the constructor parameter names. + +Because of this, it can be useful to explicitly define the constructor argument types to ensure that +the correct constructor or factory method is selected for the configured resource. + +You can specify the types as shown below: + +[source,xml] +---- + + url http://localhost + username tomee + poolSize 20 + +---- + === factory-name method In some circumstances, it may be desirable to add some additional logic diff --git a/docs/containers-and-resources.adoc b/docs/containers-and-resources.adoc index 2f5c17c5b9b..77a3c1aca2a 100644 --- a/docs/containers-and-resources.adoc +++ b/docs/containers-and-resources.adoc @@ -4,461 +4,405 @@ :jbake-type: page :jbake-status: published +== Containers -[source,xml] ----- -

----- - -CMP_ENTITY +=== CMP_ENTITY -Declarable in tomee.xml via +Declarable in `tomee.xml` via -Declarable in properties via +Declarable in properties via: +---- Foo = new://Container?type=CMP_ENTITY +---- -Supports the following properties - -Property Name - -Description - -CmpEngineFactory - -Default value is org.apache.openejb.core.cmp.jpa.JpaCmpEngineFactory. - -TransactionManager - -Declarable in tomee.xml via - -Supports the following properties +Supports the following properties: -Property Name +[cols="1,3",options="header"] +|=== +| Property Name | Description -Description +| CmpEngineFactory +| Default value is `org.apache.openejb.core.cmp.jpa.JpaCmpEngineFactory`. -defaultTransactionTimeoutSeconds +| TransactionManager +| Transaction manager used by the container. +|=== -Default value is 10 minutes. +--- -BMP_ENTITY +=== BMP_ENTITY -Declarable in tomee.xml via +Declarable in `tomee.xml` via -Declarable in properties via +Declarable in properties via: +---- Foo = new://Container?type=BMP_ENTITY +---- -Supports the following properties - -Property Name +Supports the following properties: -Description +[cols="1,3",options="header"] +|=== +| Property Name | Description -PoolSize +| PoolSize +| Specifies the size of the bean pools for this BMP entity container. +Default value is `10`. +|=== -Specifies the size of the bean pools for this bmp entity container. -Default value is 10. +--- -STATELESS +=== STATELESS -Declarable in tomee.xml via +Declarable in `tomee.xml` via -Declarable in properties via +Declarable in properties via: +---- Foo = new://Container?type=STATELESS +---- -Supports the following properties - -Property Name - -Description - -TimeOut +Supports the following properties: -Specifies the time to wait between invocations. This value is measured -in milliseconds. A value of 5 would result in a time-out of 5 -milliseconds between invocations. A value of zero would mean no timeout. -Default value is 0. +[cols="1,3",options="header"] +|=== +| Property Name | Description -PoolSize +| TimeOut +| Specifies the time to wait between invocations, in milliseconds. +A value of `0` means no timeout. +Default value is `0`. -Specifies the size of the bean pools for this stateless SessionBean -container. Default value is 10. +| PoolSize +| Specifies the size of the bean pools for this stateless SessionBean container. +Default value is `10`. -StrictPooling +| StrictPooling +| Controls behavior when the pool reaches its maximum size. +If `true`, requests wait for instances to become available and the pool never grows beyond `PoolSize`. +If `false`, temporary instances are created for one invocation and then discarded. +Default value is `true`. +|=== -StrictPooling tells the container what to do when the pool reaches it's -maximum size and there are incoming requests that need instances. With -strict pooling, requests will have to wait for instances to become -available. The pool size will never grow beyond the the set PoolSize -value. Without strict pooling, the container will create temporary -instances to meet demand. The instances will last for just one method -invocation and then are removed. Default value is true. +--- -STATEFUL +=== STATEFUL -Declarable in tomee.xml via +Declarable in `tomee.xml` via -Declarable in properties via +Declarable in properties via: +---- Foo = new://Container?type=STATEFUL +---- -Supports the following properties - -Property Name - -Description - -Passivator - -The passivator is responsible for writing beans to disk at passivation -time. Different passivators can be used by setting this property to the -fully qualified class name of the PassivationStrategy implementation. -The passivator is not responsible for invoking any callbacks or other -processing, its only responsibly is to write the bean state to disk. -Known implementations: org.apache.openejb.core.stateful.RAFPassivater -org.apache.openejb.core.stateful.SimplePassivater Default value is -org.apache.openejb.core.stateful.SimplePassivater. +Supports the following properties: -TimeOut +[cols="1,3",options="header"] +|=== +| Property Name | Description -Specifies the time to wait between invocations. This value is measured -in minutes. A value of 5 would result in a time-out of 5 minutes between -invocations. A value of zero would mean no timeout. Default value is 20. +| Passivator +| Responsible for writing beans to disk during passivation. +Known implementations: +`org.apache.openejb.core.stateful.RAFPassivater` +`org.apache.openejb.core.stateful.SimplePassivater` +Default value is `org.apache.openejb.core.stateful.SimplePassivater`. -PoolSize +| TimeOut +| Specifies the time to wait between invocations, in minutes. +A value of `0` means no timeout. +Default value is `20`. -Specifies the size of the bean pools for this stateful SessionBean -container. Default value is 1000. +| PoolSize +| Specifies the size of the bean pools for this stateful SessionBean container. +Default value is `1000`. -BulkPassivate +| BulkPassivate +| Number of instances to passivate at one time during bulk passivation. +Default value is `100`. +|=== -Property name that specifies the number of instances to passivate at one -time when doing bulk passivation. Default value is 100. +--- -MESSAGE +=== MESSAGE -Declarable in tomee.xml via +Declarable in `tomee.xml` via -Declarable in properties via +Declarable in properties via: +---- Foo = new://Container?type=MESSAGE +---- -Supports the following properties - -Property Name - -Description - -ResourceAdapter - -The resource adapter delivers messages to the container Default value is -Default JMS Resource Adapter. +Supports the following properties: -MessageListenerInterface +[cols="1,3",options="header"] +|=== +| Property Name | Description -Specifies the message listener interface handled by this container -Default value is jakarta.jms.MessageListener. +| ResourceAdapter +| Resource adapter that delivers messages to the container. +Default value is *Default JMS Resource Adapter*. -ActivationSpecClass +| MessageListenerInterface +| Message listener interface handled by this container. +Default value is `jakarta.jms.MessageListener`. -Specifies the activation spec class Default value is -org.apache.activemq.ra.ActiveMQActivationSpec. +| ActivationSpecClass +| Activation specification class. +Default value is `org.apache.activemq.ra.ActiveMQActivationSpec`. -InstanceLimit +| InstanceLimit +| Maximum number of bean instances allowed per MDB deployment. +Default value is `10`. +|=== -Specifies the maximum number of bean instances that are allowed to exist -for each MDB deployment. Default value is 10. +--- -Resources +== Resources -javax.sql.DataSource +=== javax.sql.DataSource -Declarable in tomee.xml via +Declarable in `tomee.xml` via -Declarable in properties via +Declarable in properties via: +---- Foo = new://Resource?type=javax.sql.DataSource +---- -Supports the following properties - -Property Name - -Description - -JtaManaged - -Determines wether or not this data source should be JTA managed or user -managed.  If set to 'true' it will automatically be enrolled in any -ongoing transactions.  Calling begin/commit/rollback or setAutoCommit on -the datasource or connection will not be allowed.  If you need to -perform these functions yourself, set JtaManaged to 'false' In terms of -JPA persistence.xml: "JtaManaged=true" can be used as a -'jta-data-source' "JtaManaged=false" can be used as a -'non-jta-data-source' Default value is true. - -JdbcDriver - -Driver class name Default value is org.hsqldb.jdbcDriver. - -JdbcUrl - -Url for creating connections Default value is -jdbc:hsqldb:file:data/hsqldb/hsqldb. - -UserName - -Default user name Default value is sa. - -Password - -Default password - -ConnectionProperties - -The connection properties that will be sent to the JDBC driver when -establishing new connections Format of the string must be -[propertyName=property;]* NOTE - The "user" and "password" properties -will be passed explicitly, so they do not need to be included here. - -DefaultAutoCommit - -The default auto-commit state of new connections Default value is true. - -DefaultReadOnly - -The default read-only state of new connections If not set then the -setReadOnly method will not be called. (Some drivers don't support read -only mode, ex: Informix) - -DefaultTransactionIsolation - -The default TransactionIsolation state of new connections If not set -then the setTransactionIsolation method will not be called. The allowed -values for this property are:     NONE     READ_COMMITTED     -READ_UNCOMMITTED     REPEATABLE_READ     SERIALIZABLE Note: Most JDBC -drivers do not support all isolation levels - -InitialSize - -The initial number of connections that are created when the pool is -started Default value is 0. - -MaxActive - -The maximum number of active connections that can be allocated from this -pool at the same time, or a negative number for no limit. Default value -is 20. +Supports the following properties: -MaxIdle +[cols="1,3",options="header"] +|=== +| Property Name | Description -The maximum number of connections that can remain idle in the pool, -without extra ones being released, or a negative number for no limit. -Default value is 20. +| JtaManaged +| Determines whether the datasource is JTA managed. +Default value is `true`. -MinIdle +| JdbcDriver +| JDBC driver class name. +Default value is `org.hsqldb.jdbcDriver`. -The minimum number of connections that can remain idle in the pool, -without extra ones being created, or zero to create none. Default value -is 0. +| JdbcUrl +| JDBC URL for creating connections. +Default value is `jdbc:hsqldb:file:data/hsqldb/hsqldb`. -MaxWait +| UserName +| Default username. +Default value is `sa`. -The maximum number of milliseconds that the pool will wait (when there -are no available connections) for a connection to be returned before -throwing an exception, or -1 to wait indefinitely. Default value is -1. +| Password +| Default password. -ValidationQuery +| ConnectionProperties +| Properties passed to the JDBC driver when creating connections. +Format: `[propertyName=property;]*` +`user` and `password` are passed explicitly. -The SQL query that will be used to validate connections from this pool -before returning them to the caller. If specified, this query MUST be an -SQL SELECT statement that returns at least one row. +| DefaultAutoCommit +| Default auto-commit state of new connections. +Default value is `true`. -TestOnBorrow +| DefaultReadOnly +| Default read-only state of new connections. +If not set, `setReadOnly` is not called. -If true connections will be validated before being borrowed from the -pool. If the validation fails, the connection is destroyed, and a new -conection will be retrieved from the pool (and validated). NOTE - for a -true value to have any effect, the ValidationQuery parameter must be -set. Default value is true. +| DefaultTransactionIsolation +| Default transaction isolation level. +Allowed values: `NONE`, `READ_COMMITTED`, `READ_UNCOMMITTED`, `REPEATABLE_READ`, `SERIALIZABLE`. -TestOnReturn +| InitialSize +| Initial number of connections created when the pool starts. +Default value is `0`. -If true connections will be validated before being returned to the -pool.  If the validation fails, the connection is destroyed instead of -being returned to the pool. NOTE - for a true value to have any effect, -the ValidationQuery parameter must be set. Default value is false. +| MaxActive +| Maximum number of active connections. +Default value is `20`. -TestWhileIdle +| MaxIdle +| Maximum number of idle connections. +Default value is `20`. -If true connections will be validated by the idle connection evictor (if -any). If the validation fails, the connection is destroyed and removed -from the pool NOTE - for a true value to have any effect, the -timeBetweenEvictionRunsMillis property must be a positive number and the -ValidationQuery parameter must be set. Default value is false. +| MinIdle +| Minimum number of idle connections. +Default value is `0`. -TimeBetweenEvictionRunsMillis +| MaxWait +| Maximum wait time (ms) for a connection before throwing an exception. +Default value is `-1`. -The number of milliseconds to sleep between runs of the idle connection -evictor thread. When set to a negative number, no idle connection -evictor thread will be run. Default value is -1. +| ValidationQuery +| SQL query used to validate connections. -NumTestsPerEvictionRun +| TestOnBorrow +| Validate connections before borrowing. +Default value is `true`. -The number of connectionss to examine during each run of the idle -connection evictor thread (if any). Default value is 3. +| TestOnReturn +| Validate connections before returning to the pool. +Default value is `false`. -MinEvictableIdleTimeMillis +| TestWhileIdle +| Validate connections during idle eviction runs. +Default value is `false`. -The minimum amount of time a connection may sit idle in the pool before -it is eligable for eviction by the idle connection evictor (if any). -Default value is 1800000. +| TimeBetweenEvictionRunsMillis +| Time between idle eviction runs (ms). +Default value is `-1`. -PoolPreparedStatements +| NumTestsPerEvictionRun +| Number of connections tested per eviction run. +Default value is `3`. -If true, a statement pool is created for each Connection and -PreparedStatements created by one of the following methods are -pooled:    public PreparedStatement prepareStatement(String -sql);    public PreparedStatement prepareStatement(String -sql,            int resultSetType,            int resultSetConcurrency) -Default value is false. +| MinEvictableIdleTimeMillis +| Minimum idle time before eviction. +Default value is `1800000`. -MaxOpenPreparedStatements +| PoolPreparedStatements +| Enables pooling of prepared statements. +Default value is `false`. -The maximum number of open statements that can be allocated from the -statement pool at the same time, or zero for no limit. NOTE - Some -drivers have limits on the number of open statements, so make sure there -are some resources left for the other (non-prepared) statements. Default -value is 0. +| MaxOpenPreparedStatements +| Maximum open prepared statements. +Default value is `0`. -AccessToUnderlyingConnectionAllowed +| AccessToUnderlyingConnectionAllowed +| Allows access to the raw JDBC connection. +Default value is `false`. +|=== -If true the raw physical connection to the database can be accessed -using the following construct:     Connection conn = -ds.getConnection();     Connection rawConn = ((DelegatingConnection) -conn).getInnermostDelegate();     ...     conn.close() Default is false, -because misbehaving programs can do harmfull things to the raw -connection shuch as closing the raw connection or continuing to use the -raw connection after it has been assigned to another logical -connection.  Be carefull and only use when you need direct access to -driver specific extentions. NOTE: Do NOT close the underlying -connection, only the original logical connection wrapper. Default value -is false. +--- -ActiveMQResourceAdapter +=== ActiveMQResourceAdapter -Declarable in tomee.xml via +Declarable in `tomee.xml` via -Declarable in properties via +Declarable in properties via: +---- Foo = new://Resource?type=ActiveMQResourceAdapter +---- -Supports the following properties - -Property Name - -Description - -BrokerXmlConfig +Supports the following properties: -Broker configuration Default value is -broker:(tcp://localhost:61616)?useJmx=false. +[cols="1,3",options="header"] +|=== +| Property Name | Description -ServerUrl +| BrokerXmlConfig +| Broker configuration. +Default value is `broker:(tcp://localhost:61616)?useJmx=false`. -Broker address Default value is vm://localhost?async=true. +| ServerUrl +| Broker address. +Default value is `vm://localhost?async=true`. -DataSource +| DataSource +| Datasource for message persistence. +Default value is *Default Unmanaged JDBC Database*. +|=== -DataSource for persistence messages Default value is Default Unmanaged -JDBC Database. +--- -jakarta.jms.ConnectionFactory +=== jakarta.jms.ConnectionFactory -Declarable in tomee.xml via +Declarable in `tomee.xml` via -Declarable in properties via +Declarable in properties via: +---- Foo = new://Resource?type=jakarta.jms.ConnectionFactory +---- -Supports the following properties - -Property Name - -Description - -ResourceAdapter - -Default value is Default JMS Resource Adapter. - -TransactionSupport - -Specifies if the connection is enrolled in global transaction allowed -values: xa, local or none Default value is xa. +Supports the following properties: -PoolMaxSize +[cols="1,3",options="header"] +|=== +| Property Name | Description -Maximum number of physical connection to the ActiveMQ broker Default -value is 10. +| ResourceAdapter +| Default value is *Default JMS Resource Adapter*. -PoolMinSize +| TransactionSupport +| Transaction support type: `xa`, `local`, or `none`. +Default value is `xa`. -Minimum number of physical connection to the ActiveMQ broker Default -value is 0. +| PoolMaxSize +| Maximum number of physical connections. +Default value is `10`. -ConnectionMaxWaitMilliseconds +| PoolMinSize +| Minimum number of physical connections. +Default value is `0`. -Maximum amount of time to wait for a connection Default value is 5000. +| ConnectionMaxWaitMilliseconds +| Maximum time to wait for a connection. +Default value is `5000`. -ConnectionMaxIdleMinutes +| ConnectionMaxIdleMinutes +| Maximum idle time before reclaiming a connection. +Default value is `15`. +|=== -Maximum amount of time a connection can be idle before being reclaimed -Default value is 15. +--- -jakarta.jms.Queue +=== jakarta.jms.Queue -Declarable in tomee.xml via +Declarable in `tomee.xml` via -Declarable in properties via +Declarable in properties via: +---- Foo = new://Resource?type=jakarta.jms.Queue +---- -Supports the following properties - -Property Name +Supports the following properties: -Description +[cols="1,3",options="header"] +|=== +| Property Name | Description -destination +| destination +| Name of the queue. +|=== -Specifies the name of the queue +--- -jakarta.jms.Topic +=== jakarta.jms.Topic -Declarable in tomee.xml via +Declarable in `tomee.xml` via -Declarable in properties via +Declarable in properties via: +---- Foo = new://Resource?type=jakarta.jms.Topic +---- -Supports the following properties - -Property Name +Supports the following properties: -Description +[cols="1,3",options="header"] +|=== +| Property Name | Description -destination +| destination +| Name of the topic. +|=== -Specifies the name of the topic +--- -jakarta.mail.Session +=== jakarta.mail.Session -Declarable in tomee.xml via +Declarable in `tomee.xml` via -Declarable in properties via +Declarable in properties via: +---- Foo = new://Resource?type=jakarta.mail.Session +---- No properties. From 595588004cd14c5fc35b77ea91b2ecf82c166d1c Mon Sep 17 00:00:00 2001 From: Richard Zowalla Date: Mon, 5 Jan 2026 22:26:11 +0100 Subject: [PATCH 16/19] Set ctor arguments in ServiceManager --- .../main/java/org/apache/openejb/server/ServiceManager.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/server/openejb-server/src/main/java/org/apache/openejb/server/ServiceManager.java b/server/openejb-server/src/main/java/org/apache/openejb/server/ServiceManager.java index b61394f3ea7..51fe7083642 100644 --- a/server/openejb-server/src/main/java/org/apache/openejb/server/ServiceManager.java +++ b/server/openejb-server/src/main/java/org/apache/openejb/server/ServiceManager.java @@ -42,6 +42,7 @@ import java.util.Map; import java.util.Properties; import java.util.Locale; +import java.util.stream.Collectors; import static org.apache.openejb.util.PropertyPlaceHolderHelper.holdsWithUpdate; @@ -146,6 +147,11 @@ protected ServerService initServer(final String serviceName, final Properties se serviceClass, "createServerService", null, null, serviceProperties.stringPropertyNames(), Collections.singleton(Option.NAMED_PARAMETERS)); if (factory != null) { recipe.setConstructorArgNames(factory.getParameterNames()); // can throw an exception so call it before next line + final List> argTypes = factory.getParameterTypes().stream() + .filter(t -> t instanceof Class) + .map(t -> (Class) t) + .collect(Collectors.toList()); + recipe.setConstructorArgTypes(argTypes); recipe.setFactoryMethod("createServerService"); } else if (ReflectionUtil.findStaticFactory(serviceClass, "createServerService", null, null) != null) { // old behavior, remove when sure previous check is ok recipe.setFactoryMethod("createServerService"); From 98d6f289e1882bc60d521e40e414a31d6c6668b8 Mon Sep 17 00:00:00 2001 From: Richard Zowalla Date: Mon, 5 Jan 2026 22:31:43 +0100 Subject: [PATCH 17/19] Set ctor arguments in FlushableDataSourceHandler --- .../openejb/resource/jdbc/FlushableDataSourceHandler.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/FlushableDataSourceHandler.java b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/FlushableDataSourceHandler.java index 876f18b3d76..18d8ee3ce3e 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/FlushableDataSourceHandler.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/FlushableDataSourceHandler.java @@ -16,6 +16,7 @@ */ package org.apache.openejb.resource.jdbc; +import org.apache.openejb.util.Duration; import org.apache.openejb.util.LogCategory; import org.apache.openejb.util.Logger; import org.apache.xbean.recipe.ObjectRecipe; @@ -38,6 +39,10 @@ public class FlushableDataSourceHandler implements DelegatableHandler { public static final String[] FACTORY_ARGS = new String[]{ "ServiceId", "JtaManaged", "JdbcDriver", "Definition", "MaxWaitTime", "TimeBetweenEvictionRuns", "MinEvictableIdleTime", "OpenEJBResourceClasspath" }; + public static final Class[] FACTORY_ARG_TYPES = new Class[]{ + String.class, boolean.class, Class.class, String.class, + Duration.class, Duration.class, Duration.class, + boolean.class}; private final FlushConfig config; private final ReadWriteLock lock = new ReentrantReadWriteLock(); @@ -53,7 +58,8 @@ public FlushableDataSourceHandler(final CommonDataSource original, final FlushCo private void createANewDelegate() { final CommonDataSource old = delegate.get(); try { - final ObjectRecipe recipe = new ObjectRecipe(DataSourceFactory.class.getName(), "create", FACTORY_ARGS); + final ObjectRecipe recipe = new ObjectRecipe(DataSourceFactory.class.getName(), "create", + FACTORY_ARGS, FACTORY_ARG_TYPES); recipe.allow(Option.CASE_INSENSITIVE_PROPERTIES); recipe.allow(Option.IGNORE_MISSING_PROPERTIES); recipe.allow(Option.NAMED_PARAMETERS); From 1b210574e325fb9faca82b5777c4a7a34a333151 Mon Sep 17 00:00:00 2001 From: Richard Zowalla Date: Mon, 5 Jan 2026 22:42:03 +0100 Subject: [PATCH 18/19] Remove outcommented code --- .../apache/openejb/assembler/classic/Assembler.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java index 5be7d978db6..f3d32135db4 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java @@ -3159,20 +3159,8 @@ public synchronized boolean containsKey(final Object key) { } } serviceRecipe.setProperty("Definition", PropertiesHelper.propertiesToString(props)); - //explicitly set the argument types to avoid ambiguity in factory resolution. -// serviceRecipe.setConstructorArgTypes( -// new Class[]{ -// String.class, boolean.class, Class.class, String.class, -// Duration.class, Duration.class, Duration.class, -// boolean.class} -// ); } // else: any other kind of resource relying on it? shouldnt be - //explicitly set the constructor types to avoid ambiguity in ctor resolution. -// if (serviceInfo.types.contains("Queue") || serviceInfo.types.contains(Queue.class.getName())) { -// serviceRecipe.setConstructorArgTypes(new Class[]{String.class}); -// } - replaceResourceAdapterProperty(serviceRecipe); ClassLoader loader = Thread.currentThread().getContextClassLoader(); From 670434abc6ba71925d41a818550aa966aee29f91 Mon Sep 17 00:00:00 2001 From: Richard Zowalla Date: Tue, 20 Jan 2026 19:23:50 +0100 Subject: [PATCH 19/19] Use XBEAN 4.30 release artifact --- boms/tomee-microprofile/pom.xml | 10 +++++----- boms/tomee-plume/pom.xml | 10 +++++----- boms/tomee-plus/pom.xml | 10 +++++----- boms/tomee-webprofile/pom.xml | 10 +++++----- pom.xml | 2 +- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/boms/tomee-microprofile/pom.xml b/boms/tomee-microprofile/pom.xml index d7cbea70ed2..60008dd044b 100644 --- a/boms/tomee-microprofile/pom.xml +++ b/boms/tomee-microprofile/pom.xml @@ -919,27 +919,27 @@ org.apache.xbean xbean-asm9-shaded - 4.30-SNAPSHOT + 4.30 org.apache.xbean xbean-bundleutils - 4.30-SNAPSHOT + 4.30 org.apache.xbean xbean-finder-shaded - 4.30-SNAPSHOT + 4.30 org.apache.xbean xbean-naming - 4.30-SNAPSHOT + 4.30 org.apache.xbean xbean-reflect - 4.30-SNAPSHOT + 4.30 org.bitbucket.b_c diff --git a/boms/tomee-plume/pom.xml b/boms/tomee-plume/pom.xml index 5efd77e2184..f2de3f55281 100644 --- a/boms/tomee-plume/pom.xml +++ b/boms/tomee-plume/pom.xml @@ -949,27 +949,27 @@ org.apache.xbean xbean-asm9-shaded - 4.30-SNAPSHOT + 4.30 org.apache.xbean xbean-bundleutils - 4.30-SNAPSHOT + 4.30 org.apache.xbean xbean-finder-shaded - 4.30-SNAPSHOT + 4.30 org.apache.xbean xbean-naming - 4.30-SNAPSHOT + 4.30 org.apache.xbean xbean-reflect - 4.30-SNAPSHOT + 4.30 org.bitbucket.b_c diff --git a/boms/tomee-plus/pom.xml b/boms/tomee-plus/pom.xml index 982a4ccdaca..9eba851db63 100644 --- a/boms/tomee-plus/pom.xml +++ b/boms/tomee-plus/pom.xml @@ -959,27 +959,27 @@ org.apache.xbean xbean-asm9-shaded - 4.30-SNAPSHOT + 4.30 org.apache.xbean xbean-bundleutils - 4.30-SNAPSHOT + 4.30 org.apache.xbean xbean-finder-shaded - 4.30-SNAPSHOT + 4.30 org.apache.xbean xbean-naming - 4.30-SNAPSHOT + 4.30 org.apache.xbean xbean-reflect - 4.30-SNAPSHOT + 4.30 org.bitbucket.b_c diff --git a/boms/tomee-webprofile/pom.xml b/boms/tomee-webprofile/pom.xml index 4a222ffe096..ce94ae2fdd1 100644 --- a/boms/tomee-webprofile/pom.xml +++ b/boms/tomee-webprofile/pom.xml @@ -614,27 +614,27 @@ org.apache.xbean xbean-asm9-shaded - 4.30-SNAPSHOT + 4.30 org.apache.xbean xbean-bundleutils - 4.30-SNAPSHOT + 4.30 org.apache.xbean xbean-finder-shaded - 4.30-SNAPSHOT + 4.30 org.apache.xbean xbean-naming - 4.30-SNAPSHOT + 4.30 org.apache.xbean xbean-reflect - 4.30-SNAPSHOT + 4.30 org.bitbucket.b_c diff --git a/pom.xml b/pom.xml index 36e1f2b3324..8dd8900500c 100644 --- a/pom.xml +++ b/pom.xml @@ -135,7 +135,7 @@ 1.2.6 2.5.1 - 4.30-SNAPSHOT + 4.30 2.4.21 11.0.20 3.11.1