So as Romain mentions in the "feedback on cxf config" email we were kicking around ideas on better configuration. As that was partially implemented, just wanted to post more explicitly on it and make it clear the topic is completely open for discussion and ideas.
Descriptors tend to last for several years, so getting one we all like is really important. The more feedback the better. [Please respond inline and don't top-post or the thread will be unreadable. Just trim the email down to the parts that pertain to the response and respond below the part] # The Trouble with our non-extensible descriptors The issue with the current descriptor(s) is that it would be nice to have one file to rule them all. Rather than resources.xml and openejb-jar.xml and now application.properties or module.properties, have just one that: - fits any current scenario - room for any future need # Modeling internal objects So here is one idea which models after internal objects we have `AppContext`, `ModuleContext` and `BeanContext` http://svn.apache.org/repos/asf/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/AppContext.java http://svn.apache.org/repos/asf/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/ModuleContext.java http://svn.apache.org/repos/asf/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/BeanContext.java And their parent class, `DeploymentContext` http://svn.apache.org/repos/asf/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/DeploymentContext.java That xml might look like this: <AppContext> <Configuration> <AsynchronousPool> CorePoolSize = 10 MaximumPoolSize = 10 </AsynchronousPool> <AnyPropertyPrefix> someproperty = foo </AnyPropertyPrefix> <org.quartz> scheduler.instanceName = my-app scheduler.instanceId = my-bean threadPool.threadCount = 10 threadPool.class = org.superbiz.MyCustomThreadPool plugin.LogPlugin.class = org.superbiz.MyLogPlugin plugin.LogPlugin.active = true </org.quartz> </Configuration> <ModuleContext> <BeanContext id="CalculatorBean"> <Configuration> <cxf.jaxws> in-interceptors = wss4j </cxf.jaxws> </Configuration> </BeanContext> </ModuleContext> <Resources> <Service id="wss4j" class-name="org.apache.openejb.server.cxf.config.WSS4JInInterceptorFactory" factory-name="create"> action = UsernameToken passwordType = PasswordText passwordCallbackClass = org.superbiz.ws.security.PasswordCallbackHandler </Service> <Service .../> <Resource .../> </Resources> <AppContext> ## Configuration The "<Configuration>" bucket is essentially a properties bucket and would be identical to application.properties. All the data declared in "<Configuration>" would go straight into AppContext.getProperties(). The tags are simply "fanciness" for being lazy. So this is: <Configuration> <AsynchronousPool> CorePoolSize = 10 MaximumPoolSize = 10 </AsynchronousPool> <AnyPropertyPrefix> someproperty = foo </AnyPropertyPrefix> <org.quartz> scheduler.instanceName = my-app scheduler.instanceId = my-bean threadPool.threadCount = 10 threadPool.class = org.superbiz.MyCustomThreadPool plugin.LogPlugin.class = org.superbiz.MyLogPlugin plugin.LogPlugin.active = true </org.quartz> </Configuration> .. would be the same as this: <Configuration> AsynchronousPool.CorePoolSize = 10 AsynchronousPool.MaximumPoolSize = 10 AnyPropertyPrefix.someproperty = foo org.quartz.scheduler.instanceName = my-app org.quartz.scheduler.instanceId = my-bean org.quartz.threadPool.threadCount = 10 org.quartz.threadPool.class = org.superbiz.MyCustomThreadPool org.quartz.plugin.LogPlugin.class = org.superbiz.MyLogPlugin org.quartz.plugin.LogPlugin.active = true </Configuration> Both would actually function. User preference would dictate which is used. Thoughts? Given the choice, which would you use? See any third options that might be cooler? AppContext, ModuleContext, and BeanContext would each get a `<Configuration>` bucket. There might be a better name than `<Configuration>`. Maybe `<Properties>` or perhaps even better, `<Options>` ? Here's an example of how we use these Options: public static AsynchronousPool create(AppContext appContext) { Options options = appContext.getOptions(); int corePoolSize = options.get("AsynchronousPool.CorePoolSize", 10); // Default setting is for a fixed pool size, MaximumPoolSize==CorePoolSize int maximumPoolSize = Math.max(options.get("AsynchronousPool.MaximumPoolSize", corePoolSize), corePoolSize); // Default QueueSize is bounded using the MaximumPoolSize int size = options.get("AsynchronousPool.QueueSize", maximumPoolSize); // Keep Threads inactive threads alive for 60 seconds by default Duration keepAliveTime = options.get("AsynchronousPool.KeepAliveTime", new Duration(60, TimeUnit.SECONDS)); // All threads can be timed out by default boolean allowCoreThreadTimeout = options.get("AsynchronousPool.AllowCoreThreadTimeOut", true); // If the user explicitly set the QueueSize to 0, we default QueueType to SYNCHRONOUS ExecutorBuilder.QueueType defaultQueueType = (size == 0) ? ExecutorBuilder.QueueType.SYNCHRONOUS : ExecutorBuilder.QueueType.LINKED; BlockingQueue queue = options.get("AsynchronousPool.QueueType", defaultQueueType).create(options, "AsynchronousPool", size); ThreadFactory factory = new DaemonThreadFactory("AsynchronousPool"); Duration duration = options.get("AsynchronousPool.OfferTimeout", new Duration(30, TimeUnit.SECONDS)); RejectedExecutionHandler handler = new OfferRejectedExecutionHandler(duration); ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize , maximumPoolSize , keepAliveTime.getTime() , keepAliveTime.getUnit() != null ? keepAliveTime.getUnit() : TimeUnit.SECONDS , queue , factory , handler ); threadPoolExecutor.allowCoreThreadTimeOut(allowCoreThreadTimeout); return new AsynchronousPool(threadPoolExecutor); } ## EJB vs Pojo Some of the things we need to configure are not EJBs and don't have the BeanContext object internally. These are typically Pojo @WebService and JAX-RS resources and still need many of the same configuration related to @WebService related and JAX-RS. There are two thoughts on how to deal with that: - Let people use BeanContext anyway - Make a new element If we made a new element it might look like this: <AppContext> <ModuleContext> <BeanContext id="CalculatorBean"> <Configuration> <cxf.jaxws> in-interceptors = wss4j </cxf.jaxws> </Configuration> </BeanContext> <Pojo id="org.foo.bar"> <Configuration> <cxf.jaxws> in-interceptors = wss4j </cxf.jaxws> </Configuration> </Pojo> </ModuleContext> </AppContext> Pojo's don't have names like EJBs so if we use the same xml element, users will need to know to use a class name as the ID for a pojo and the ejbName if it's a bean. Ideas on something better? Better names maybe? Perhaps `<PojoContext>` for consistency. Perhaps get really basic and `<ClassContext>` ? ## Standalone apps vs apps with many modules In scenarios where there is an actual EAR file there will be several jars and wars and each will need the ability to have it's own `<ModuleContext>` and configure the `<BeanContext>` and more that apply now to modules as well as anything in the future that might be needed or desired for configuring a module. In this EAR situation, allowing `<ModuleContext>` to be a root element in say a file named module-context.xml would do the trick. That isn't the normal case, however. In most cases it's a simple war file which in Java EE terms makes it a "standalone application". With a standalone application internally you still get an AppContext, but it will only contain one ModuleContext. From a user's perspective it is just one thing. Do we want to make users always use `<ModuleContext>` or do we want to implicitly allow anything that might go into a `<ModuleContext>` to also reside in `<AppContext>`? So for example, instead of: <AppContext> <ModuleContext> <BeanContext id="CalculatorBean"> <Configuration> <cxf.jaxws> in-interceptors = wss4j </cxf.jaxws> </Configuration> </BeanContext> <Pojo id="org.foo.bar"> <Configuration> <cxf.jaxws> in-interceptors = wss4j </cxf.jaxws> </Configuration> </Pojo> </ModuleContext> </AppContext> Allow this: <AppContext> <BeanContext id="CalculatorBean"> <Configuration> <cxf.jaxws> in-interceptors = wss4j </cxf.jaxws> </Configuration> </BeanContext> <Pojo id="org.foo.bar"> <Configuration> <cxf.jaxws> in-interceptors = wss4j </cxf.jaxws> </Configuration> </Pojo> </AppContext> The Pros are nearly inverse to the Cons. For requiring `<ModuleContext>`: Pros: - Clearly states what applies to that one jar (module) - Flexibility to add to `<ModuleContext>` without worry of adverse impact on also allowing those things in `<AppContext>` - If `id` is left off of `<ModuleContext id="foo">`, we can assume that to be the only module in the standalone application. Cons: - Feels unnatural in a standalone application scenario - If a user specifies more than one `<ModuleContext>` of a standalone application we will have to treat that as a deployment error - If `id` is left off of `<ModuleContext id="foo">` of an ear we will have to treat that as a deployment error For allowing `<AppContext>` to serve implicitly as a `<ModuleContext>`: Pros: - Feels natural in a standalone application scenario Cons: - Must be treated as an error in a ear scenario - If a user does both and puts `<BeanContext>` elements under `<AppContext>` and under a `<ModuleContext>` it is awkward at best, possibly an error if definitions conflict - We'll be restricted in that anything we might want to add to `<ModuleContext>` in the future must also make sense in `<AppContext>` Do we have any thoughts on that? Preferences or other ideas? Does it help if we make a different containing element with a better name, perhaps `<StandaloneContext>`? <AppContext> <StandaloneContext> <BeanContext id="CalculatorBean"> <Configuration> <cxf.jaxws> in-interceptors = wss4j </cxf.jaxws> </Configuration> </BeanContext> <Pojo id="org.foo.bar"> <Configuration> <cxf.jaxws> in-interceptors = wss4j </cxf.jaxws> </Configuration> </Pojo> </StandaloneContext> <Resources> <Resource ...> <Service ...> </Resources> </AppContext> Or perhaps we want an entirely different root element for standalone apps? <StandaloneAppContext> <BeanContext id="CalculatorBean"> <Configuration> <cxf.jaxws> in-interceptors = wss4j </cxf.jaxws> </Configuration> </BeanContext> <Pojo id="org.foo.bar"> <Configuration> <cxf.jaxws> in-interceptors = wss4j </cxf.jaxws> </Configuration> </Pojo> <Resources> <Resource ...> <Service ...> </Resources> </StandaloneAppContext> Or maybe since EARs are the least common scenario, we give them the funny root element: <EnterpriseAppContext> <ModuleContext id="FooModule"> <BeanContext id="CalculatorBean"> <Configuration> <cxf.jaxws> in-interceptors = wss4j </cxf.jaxws> </Configuration> </BeanContext> <Pojo id="org.foo.bar"> <Configuration> <cxf.jaxws> in-interceptors = wss4j </cxf.jaxws> </Configuration> </Pojo> </ModuleContext> <Resources> <Resource ...> <Service ...> </Resources> </EnterpriseAppContext> Looking forward to as many responses as possible. -David
