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


Reply via email to