Jerome,
Yes, I think it could work generically. My intent at this point is to
support all the existing create() methods (lots of examples in AMX
com.sun.appserv.management.config.DomainConfig).
Each create() method would have its own method name (not a generic
name), which yields the return type and its own signature(no Java
generic types involved here). All parameters are 'String'. The
'optional' Map contain any other attributes which need not be
specified, but can be for convenience and atomicity. In short, I'm
looking for 100% V2 compatibility.
Some of many possible variants:
public interface SomeAMXConfig extends AMXConfig, Container {
// no annotation is actually needed, "name" and "optional" can be
assumed as default names
// and @AMXConfigInfo for Abc already offers a nameHint() so that
name could be "name", "id", etc.
@ConfigCreate(paramNames={"name","optional"})
public Abc createAbcConfig( String name, Map<String,String>
optional);
// no annotation is actually needed; generic form just sets what's
there
@ConfigCreate
public Def createDefConfig( Map<String,String> optional);
// annotation *required*; the attribute "port-number" cannot be
deduced
@ConfigCreate(paramNames={ "name", "classname", "port-number"})
public Xyz createXyzConfig( String name, String classname, String
portNumber, Map<String,String> optional);};
}
AMX needs the following to make it work;
0. Consistent naming pattern. Easy, this is done today in V2 AMX
interfaces. Future methods would have to conform to the pattern for
automatic support.
1. Deduce the sub-interface of AMXConfig which is involved. This
part is easy; it's the return type of the method.
2. Parameter names: missing. This is what @ParamNames is needed; it
allows
3. Ability to get the <? extends ConfigBeanProx) interface (the
@Configured interface) so that it can be instantiated.
====> #3 is what I need your help on. Given the name "Abc" or "Xyz",
that needs to (somehow) find the matching @Configured interface. This
could be a textual match (which is inflexible and might not always be
feasible), or perhaps the annotation can include hint at the classnam
eg:
@ConfigCreate(classHint="org.webstuff.alphabet.XyzConfigStuff",
paramNames={ "name", "classname", "port-number"})
public Xyz createXyzConfig( String name, String classname, String
portNumber, Map<String,String> optional);};
Lloyd
On Mar 17, 2008, at 10:20 PM, Jerome Dochez wrote:
> So if I understand the pattern correctly, you have named parameters
> for required parameters and all others are passed in the optional
> map ?
>
> so we have some like :
>
> <T> T createTConfig(T.param1, T.param2, Map<String, String optionals)
>
> T.param1 are @Attribute declared on T with required=true, all other
> T attributes go in optionals.
>
> for Instance take in Domain.java, for JdbcResource, the above
> automatic mapping with today's @Attribute would lead to
>
> JdbcResource createJdbcResourceConfig(String jndi-name, String pool-
> name, Map<String, String> optionals);
>
> that seem remarkably close to https://glassfish.dev.java.net/nonav/javaee5/amx/javadoc/com/sun/appserv/management/config/DomainConfig.html
> #createJDBCResourceConfig(java.lang.String,%20java.lang.String,
> %20java.util.Map)
>
> but of course, it's only 1 example. do you think this could work
> generically ?
>
> jerome
>
> On Mar 17, 2008, at 11:05 AM, Lloyd L Chambers wrote:
>
>> Jerome,
>>
>> I am averse to any system that would require special processing to
>> generate the info ("APT"). An annotation is something that anyone
>> can add and compile at will with any build system eg a 3rd party
>> with their own build system or java compiler--and it seems very
>> straightforward. But I don't understand your proposal about APT.
>>
>> For an example of the types of create() methods seen today, take a
>> look at AMX DomainConfig:
>> https://glassfish.dev.java.net/nonav/javaee5/amx/javadoc/com/sun/appserv/management/config/DomainConfig.html
>>
>> All AMX creation methods for config start with "create" and end
>> with "Config" and are scoped by the containing AMXConfig MBean
>> ("Container"). These facts allow enough knowledge about what to be
>> created to implement it in general (I think).
>>
>> There are alternatives to methods with specific names. AMX could
>> offer this type of generic facility:
>> create( String j2eeType, Map<String,String> attributes );
>>
>> But the above actually introduces additional complexities (eg
>> required parameters are not specified), and it breaks backward
>> compatibility.
>>
>> Lloyd
>>
>> On Mar 17, 2008, at 10:47 AM, Jerome Dochez wrote:
>>
>>>
>>> On Mar 17, 2008, at 10:17 AM, Lloyd L Chambers wrote:
>>>
>>>> Jerome,
>>>>
>>>> The AMX code does map names back and forth already. But there
>>>> are no names to begin with--an MBean operation will be invoked
>>>> like this:
>>>>
>>>> public final Object invoke(
>>>> String operationName,
>>>> Object[] args,
>>>> String[] types )
>>>>
>>>> There are no argument names here, so nothing to use for mapping.
>>>> AMX needs to map args[1..N] to names which can eventually result
>>>> in xml property names.
>>>>
>>>> If a method to create an "Abc" eg createAbc() method has been
>>>> declared in the AMX interface, then the args could be matched up
>>>> to the parameter names, but HOW?
>>>>
>>> I understand now, thanks
>>>> I don't know of any mechanism to get the *names* of parameters
>>>> from a java.lang.reflect.Method, or can you?
>>> no there isn't a way to do that with reflection but we could use
>>> APT to generate that information automatically.
>>>
>>> where would these createABC be located ?
>>>
>>> Jerome
>>>
>>>> That is why I thought an annotation was needed, which would allow
>>>> the names of each parameter in the parameter list to be named.
>>>>
>>>> Lloyd
>>>>
>>>> On Mar 14, 2008, at 10:44 PM, Jerome Dochez wrote:
>>>>
>>>>> for issue 2, I don't understand why you cannot (at least for 99%
>>>>> of the cases) calculate automatically the amx name from the xml
>>>>> name and the other way around. seems extremely verbose to me if
>>>>> you have to specify it on an annotation when the mapping is
>>>>> simple like in you previous email
>>>>>
>>>>> ex:
>>>>> @ParamNames("jndi-name","jndi-lookup-name","res-type","factory-
>>>>> class")
>>>>> createJNDIResourceConfig( String jndiName, String
>>>>> jndiLookupName, String resType, String factoryClass,
>>>>> Map<String,String> optional);
>>>>>
>>>>>
>>>>> On Mar 14, 2008, at 9:56 AM, Lloyd Chambers wrote:
>>>>>
>>>>>> Jerome et al,
>>>>>>
>>>>>> To support AMX create(), I need a few things which perhaps you
>>>>>> can tell me how to do—
>>>>>>
>>>>>> => ISSUE 1: locating an @Configured
>>>>>>
>>>>>> To locate the @Configured interface corresponding to an AMX
>>>>>> j2eeType. This value is found in the @AMXConfigInfo, which
>>>>>> annotates an @Configured interface. AMX requires that any
>>>>>> module desiring automatic AMXConfig support annotate its config
>>>>>> with @AMXConfigInfo. So I need to do this (in some form):
>>>>>>
>>>>>> for ( final Class<? extends AMXConfig> configIntf :
>>>>>> allConfiguredClasses ) {
>>>>>> AMXConfigInfo configInfo =
>>>>>> configIntf.getAnnotation( AMXConfigInfo.class );
>>>>>> if ( configInfo != null &&
>>>>>> configInfo.j2eeType().equals( j2eeType ) {
>>>>>> // found a match
>>>>>> break;
>>>>>> }
>>>>>> }
>>>>>> Such a loop could be run just once (on demand when the first
>>>>>> create() is done), and a Map could be created at that time for
>>>>>> future efficiency. Alternately, it could exit as soon as the
>>>>>> required value were found.
>>>>>>
>>>>>> Alternately, create() is always implicitly for a child
>>>>>> (Containee) and therefore the only classes that need to be
>>>>>> searched are those that are child elements of an existing
>>>>>> ConfigBean. Is there a method to get all possible child
>>>>>> interfaces for a given ConfigBean (not just those that
>>>>>> currently exist)?
>>>>>>
>>>>>> => ISSUE 2: mapping parameter names
>>>>>>
>>>>>> To support create() methods with explicit parameter lists. For
>>>>>> example:
>>>>>>
>>>>>> createJNDIResourceConfig( String jndiName, String
>>>>>> jndiLookupName, String resType, String factoryClass,
>>>>>> Map<String,String> optional);
>>>>>>
>>>>>> The problem here is mapping jndiName, jndiLookupName, resType
>>>>>> and factoryClass to XML names; as incoming parameters they are
>>>>>> simple indexed values in the parameter list, lacking any sort
>>>>>> of name. AMX solves this today by having small mapping tables
>>>>>> internally, but that means special code for every such method,
>>>>>> something we must avoid in a pluggable system.
>>>>>>
>>>>>> I’m thinking of using an annotation which specifies the names
>>>>>> for explicit parameters:
>>>>>>
>>>>>> @Target(ElementType.METHOD)
>>>>>> public @interface ParamNames {
>>>>>> /** comma-delimited list of parameter names, in order */
>>>>>> String paramNames default "";
>>>>>> }
>>>>>>
>>>>>> ex:
>>>>>> @ParamNames("jndi-name","jndi-lookup-name","res-type","factory-
>>>>>> class")
>>>>>> createJNDIResourceConfig( String jndiName, String
>>>>>> jndiLookupName, String resType, String factoryClass,
>>>>>> Map<String,String> optional);
>>>>>>
>>>>>> Thoughts?
>>>>>>
>>>>>> Lloyd
>>>>>>
>>>>>> Begin forwarded message:
>>>>>>
>>>>>>> From: Lloyd Chambers <lloyd.chambers_at_mac.com>
>>>>>>> Date: March 14, 2008 9:36:02 AM PDT
>>>>>>> To: admin_at_glassfish.dev.java.net
>>>>>>> Subject: Glassfish V3: should AMX preserve create() methods
>>>>>>> for backwards compatibility?
>>>>>>>
>>>>>>> This is a sort of “thinking aloud” and request for feedback
>>>>>>> all in one—
>>>>>>>
>>>>>>> Background
>>>>>>>
>>>>>>> - In V3 arbitrary modules can be loaded, including ones
>>>>>>> designed and compiled after the product ships
>>>>>>> - AMX supports configuration MBeans for such modules
>>>>>>> automagically with a simple annotation on the @Configured
>>>>>>> interface supplied by the module
>>>>>>>
>>>>>>> In V2, AMX supported creation of sub-elements with createAbc()
>>>>>>> methods that included a parameter list with explicit
>>>>>>> parameters for required values and optional parameters
>>>>>>> provided in a Map<String,String>. Here are a few examples
>>>>>>> from DomainConfig:
>>>>>>>
>>>>>>> createStandaloneServerConfig(String name, String
>>>>>>> nodeAgentName, String configName, Map<String,String> optional);
>>>>>>>
>>>>>>> createConfigConfig( String name, Map<String,String> optional );
>>>>>>>
>>>>>>> createLoadBalancerConfig(String name, String lbConfigName,
>>>>>>> boolean autoApplyEnabled, Map<String,String> optional);
>>>>>>>
>>>>>>> createJNDIResourceConfig( String jndiName, String
>>>>>>> jndiLookupName, String resType, String factoryClass,
>>>>>>> Map<String,String> optional);
>>>>>>>
>>>>>>> createJDBCConnectionPoolConfig( String name,
>>>>>>> String connectionValidationMethod,
>>>>>>> String datasourceClassname,
>>>>>>> boolean failAllConnections,
>>>>>>> int idleTimeoutSeconds,
>>>>>>> boolean connectionValidationRequired,
>>>>>>> boolean isolationLevelGuaranteed,
>>>>>>> String transactionIsolationLevel,
>>>>>>> int maxPoolSize,
>>>>>>> int maxWaitTimeMillis,
>>>>>>> int poolResizeQuantity,
>>>>>>> String resType,
>>>>>>> int steadyPoolSize,
>>>>>>> String databaseName,
>>>>>>> String databaseUserName,
>>>>>>> String databasePassword,
>>>>>>> Map<String,String> reservedForFutureUse );
>>>>>>>
>>>>>>> Question: In Glassfish V3, should AMX preserve methods like
>>>>>>> the ones shown above?
>>>>>>>
>>>>>>> (and allow/support such methods in new/unknown AMX interfaces
>>>>>>> supplied by arbitrary modules)
>>>>>>>
>>>>>>> I think the answer is “yes”, so long as the backend can
>>>>>>> implement this support generically: AMX needs to be able to
>>>>>>> turn the parameter list into a generic form (eg a Map) which
>>>>>>> can be generically set on a ConfigBean. AMX can supply the
>>>>>>> “glue” code to transform the explicit and optional parameters
>>>>>>> into a form which can be used to set values on a ConfigBean eg:
>>>>>>>
>>>>>>> public MyConfig createContainee( final String j2eeType, final
>>>>>>> Map<String,String> values );
>>>>>>>
>>>>>>> implemented by:
>>>>>>>
>>>>>>> final ConfigBean configBean =
>>>>>>> instantiateConfigBeanForJ2EEType( j2eeType );
>>>>>>> for( final String fieldName : values.keySet() ) {
>>>>>>> configBean.attribute( amxNameToXmlName( fieldName ),
>>>>>>> values.get( fieldName ) );
>>>>>>> }
>>>>>>>
>>>>>>> Fortunately, the j2eeType value is found in the
>>>>>>> @AMXConfigInfo, so this all ought to work OK.
>>>>>>>
>>>>>>> Lloyd
>>>>>>
>>>>>
>>>>
>>>> ---
>>>> Lloyd L Chambers
>>>> lloyd.chambers_at_sun.com
>>>> Sun Microsystems, Inc
>>>>
>>>>
>>>>
>>>
>>
>> ---
>> Lloyd L Chambers
>> lloyd.chambers_at_sun.com
>> Sun Microsystems, Inc
>>
>>
>>
>
---
Lloyd L Chambers
lloyd.chambers_at_sun.com
Sun Microsystems, Inc