admin@glassfish.java.net

Re: HK2 talk tomorrow (1/22) at 11 am PST

From: Kohsuke Kawaguchi <Kohsuke.Kawaguchi_at_Sun.COM>
Date: Fri, 25 Jan 2008 12:11:51 -0800

If every integration points use the same set of properties, then you are
right that there's not much point in defining them differently. Tabs and
tree nodes are certainly similar enough that I agree having a single
interface is sufficient.

But I guess I was assuming that there are other extension points that
are somewhat different --- for example, the extension point for custom
branding, the extension point for "common tasks" list, the extension
point for the different filtering types, etc.

The other part of the reasoning for me was that I meant these different
extension point implementations to serve as the model object, in which
case strongly typing them has more meaning. But if these are only used
as implementation-detail in-memory data structure inside admin module
(and people are writing them in XML, as in your earlier proposals), then
  this doesn't matter much.


Ken Paulsen wrote:
>
> I'd also like to look at this from the perspective of a consumer of
> these "integration points." Which of these is preferable?
>
> #1:
>
> // Get integration points for the "tree"
> List<IntegrationPoint> points = service.getIntegrationPoints("myTree");
> for (IntegrationPoint point : points) {
> point.getId();
> point.priority();
> point.getParentId();
> point.getContent();
> }
> // Same api's for "tab" (and everything else):
> points = service.getIntegrationPoints("applicationTab");
> for (IntegrationPoint point : points) {
> point.getId();
> point.priority();
> point.getParentId();
> point.getContent();
> }
>
>
>
> #2:
>
> // Get integration points for the "tree"
> List<TreeIntegrationPoint> treePoints =
> service.getTreeIntegrationPoints("myTree");
> for (TreeIntegrationPoint treePoint : treePoints) {
> treePoint.getId();
> treePoint.priority();
> treePoint.getParentId();
> treePoint.getContent();
> }
> // Different api's for "tab" (and everything else):
> List<TabIntegrationPoint> tabPoints =
> service.getTabIntegrationPoints("applicationTab");
> for (TabIntegrationPoint tabPoint : tabPoints) {
> tabPoint.getId();
> tabPoint.priority();
> tabPoint.getParentId();
> tabPoint.getContent();
> }
>
>
>
> These two examples assume that we are describing the integration point,
> not the content of the integration point (i.e. strategies #1 or #2
> below). I am not clear on if "service" in the second example would
> actually need to be 2 service objects (i.e. 1 for each new type of
> "IntegrationPoint"). Or perhaps we can have a base IntegrationPoint
> type and a single api which will return a List with typed children. I
> always struggle in a situation like that to get the <generics> declared
> correctly to avoid casting... but maybe it can be done.
>
> Anyway here are my thoughts on advantages / disadvantages:
>
> Advantages for #1:
>
> * Concise API (one class to learn, not one for every type).
> * Easier to write generic code to handle any type of
> IntegrationPoint, even ones that don't exist today.
>
> Advantages for #2:
>
> * Code completion (although, if we don't have anything different
> between IntegrationPoint types... this won't matter much).
> * Code is easier to read
>
> Since the content of the IntegrationPoints is likely to be the main
> differentiator between these objects... and in cases #1 & #2 the content
> is opaque, I see little value in adding new class types. If we go with
> approach #3, then the entire content of the GUI is described in these
> objects and it would make a lot of sense to have many different types.
> We should also keep in mind, that the "integrator's" interface should
> typically be via the XML (or other markup)... only the admin GUI team,
> or someone writing code to consume integration points will see this API.
>
> Let me know your thoughts and/or what I'm missing!
>
> Thanks,
>
> Ken
>
>
> Ken Paulsen wrote:
>>
>> As discussed in the meeting, here are some options on how a integrator
>> could specify these integration points (in all cases I will show tab
>> and tree examples, although other types like help, button, text,
>> custom java code, etc need to also work).
>>
>> *#1) "annotate" a JSF page fragment:*
>>
>> id: myTab
>> type: applicationTab
>> priority: 22
>> parentId: webApplicationTab
>>
>> <sun:tab id="general" immediate="true"
>> text="$resource{i18n.common.General}" >
>> <!command
>> setSessionAttribute(key="appGeneralTabs" value="general");
>> urlencode(value="#{name}", value=>$pageSession{name});
>> redirect(page="#{generalPage}?appName=#{name}");
>> />
>> </sun:tab>
>>
>>
>>
>> id: jbiRootNode
>> type: treeNode
>> priority: 840
>> parentId: rootNode
>>
>> <sun:treeNode id="JBIRoot"
>> expanded="true"
>> rendered="#{JBIHookBean.jbiJarsAvailable &&
>> JBIConfigBean.jbiEnabled}"
>> target="main"
>> text="$resource{i18n.tree.jbi.root}"
>> toolTip="$resource{i18n.tree.jbi.root.toolTip}"
>> url="jbi/pe/root.jsf">
>> <!facet image>
>> <sun:iconHyperlink id="image" icon="TREE_FOLDER"
>> url="jbi/pe/root.jsf" target="main" border="0" immediate="true"
>> toolTip="$resource{i18n.tree.jbi.root.toolTip}" />
>> </facet>
>>
>> <dynamicTreeNode id="jbiDeployments"
>> childExpanded="false"
>> childImageURLbase="resource/images/jbi/"
>> childTarget="main"
>> childURLbase="/jbi/pe/showDeployment.jsf?"
>> expanded="false"
>> rendered="#{JBIHookBean.jbiJarsAvailable &&
>> JBIConfigBean.jbiEnabled}"
>> target="main"
>> text="$resource{i18n.tree.jbi.deployments}"
>> toolTip="$resource{i18n.tree.jbi.deployments.toolTip}"
>> treeAdaptorClass="com.sun.jbi.jsf.util.JBIHookTreeAdaptor"
>> treeAdaptorListType="deployments"
>> url="/jbi/pe/deployments.jsf">
>> <!facet image>
>> <sun:iconHyperlink id="saLink" icon="TREE_FOLDER"
>> url="/jbi/pe/deployments.jsf" target="main" border="0"
>> immediate="true" />
>> </facet>
>> </dynamicTreeNode>
>>
>>
>>
>> Advantages:
>>
>> * Cut/paste existing code (faster development from v2 -> v3)
>> * 1 file to add an integration into GUI
>>
>> Disadvantages:
>>
>> * Exposes JSF directly as integration mechanism (harder for
>> non-jsf integrators)
>>
>> Requires:
>>
>> * Custom "ConfigParser"
>>
>>
>> *#2) Separate Configuration, still use .jsf pages/fragments:
>> *
>> <?xml version="1.0" encoding="UTF-8"?>
>> <!DOCTYPE gui-config PUBLIC ...>
>>
>> <gui-config id="myIntegration">
>> <tab id="myTab" type="webApplicationTab" priority="22"
>> parentId="webApplicationTab" uri="/myTab.jsf" />
>> <treeNode id="jbiRootNode" priority="840" parentId="rootNode"
>> uri="/myTreeNode.jsf" />
>> </gui-config>
>>
>>
>> */myTab.jsf:*
>> <sun:tab id="general" immediate="true"
>> text="$resource{i18n.common.General}" >
>> <!command
>> setSessionAttribute(key="appGeneralTabs" value="general");
>> urlencode(value="#{name}", value=>$pageSession{name});
>> redirect(page="#{generalPage}?appName=#{name}");
>> />
>> </sun:tab>
>>
>>
>> */myTreeNode.jsf:*
>> <sun:treeNode id="JBIRoot"
>> expanded="true"
>> rendered="#{JBIHookBean.jbiJarsAvailable &&
>> JBIConfigBean.jbiEnabled}"
>> target="main"
>> text="$resource{i18n.tree.jbi.root}"
>> toolTip="$resource{i18n.tree.jbi.root.toolTip}"
>> url="jbi/pe/root.jsf">
>> <!facet image>
>> <sun:iconHyperlink id="image" icon="TREE_FOLDER"
>> url="jbi/pe/root.jsf" target="main" border="0" immediate="true"
>> toolTip="$resource{i18n.tree.jbi.root.toolTip}" />
>> </facet>
>>
>> <dynamicTreeNode id="jbiDeployments"
>> childExpanded="false"
>> childImageURLbase="resource/images/jbi/"
>> childTarget="main"
>> childURLbase="/jbi/pe/showDeployment.jsf?"
>> expanded="false"
>> rendered="#{JBIHookBean.jbiJarsAvailable &&
>> JBIConfigBean.jbiEnabled}"
>> target="main"
>> text="$resource{i18n.tree.jbi.deployments}"
>> toolTip="$resource{i18n.tree.jbi.deployments.toolTip}"
>> treeAdaptorClass="com.sun.jbi.jsf.util.JBIHookTreeAdaptor"
>> treeAdaptorListType="deployments"
>> url="/jbi/pe/deployments.jsf">
>> <!facet image>
>> <sun:iconHyperlink id="saLink" icon="TREE_FOLDER"
>> url="/jbi/pe/deployments.jsf" target="main" border="0"
>> immediate="true" />
>> </facet>
>> </dynamicTreeNode>
>>
>>
>>
>> Advantages:
>>
>> * Cut/paste existing code (faster development from v2 -> v3)
>> * Separation of configuration makes re-use easier (i.e. includes)
>> * Content is kept out of configuration
>> * May be able to leverage existing ConfigParser
>>
>> Disadvantages:
>>
>> * Exposes JSF directly as integration mechanism (harder for
>> non-jsf integrators)
>>
>> Requires:
>>
>> *
>>
>>
>>
>> *#3) Abstract JSF, use "@Configured" beans for meta-data*
>>
>> NOTE: XML syntax of ".gui" files would need to be defined. It could
>> be extensible via the hk2 ConfigParser. It may be able to generalize
>> gui concepts such as tabs/trees/menus more easily and could adapt to
>> different technologies besides JSF. Some of the JSF concepts (i.e.
>> "immediate") may have to be removed, or be renamed to abstract them.
>>
>> <?xml version="1.0" encoding="UTF-8"?>
>> <!DOCTYPE gui-config PUBLIC ...>
>>
>> <gui-config id="myIntegration">
>> <tab id="myTab" type="webApplicationTab" priority="22"
>> parentId="webApplicationTab" uri="/myTab.gui" />
>> <treeNode id="jbiRootNode" priority="840" parentId="rootNode"
>> uri="/myTreeNode.gui" />
>> </gui-config>
>>
>>
>> */myTab.gui:*
>> <tab id="general" immediate="true" text="#{i18n.common.General}" >
>> <event type="command">
>> setSessionAttribute(key="appGeneralTabs" value="general");
>> urlencode(value="#{name}", value=>$pageSession{name});
>> redirect(page="#{generalPage}?appName=#{name}");
>> </event>
>> </tab>
>>
>>
>> */myTreeNode.jsf:*
>> <treeNode id="JBIRoot"
>> expanded="true"
>> rendered="#{JBIHookBean.jbiJarsAvailable &&
>> JBIConfigBean.jbiEnabled}"
>> target="main"
>> text="#{i18n.tree.jbi.root}"
>> toolTip="#{i18n.tree.jbi.root.toolTip}"
>> url="jbi/pe/root.jsf">
>> <facet name="image">
>> <iconHyperlink id="image" icon="TREE_FOLDER"
>> url="jbi/pe/root.jsf" target="main" border="0" immediate="true"
>> toolTip="#{i18n.tree.jbi.root.toolTip}" />
>> </facet>
>>
>> <dynamicTreeNode id="jbiDeployments"
>> childExpanded="false"
>> childImageURLbase="resource/images/jbi/"
>> childTarget="main"
>> childURLbase="/jbi/pe/showDeployment.jsf?"
>> expanded="false"
>> rendered="#{JBIHookBean.jbiJarsAvailable &&
>> JBIConfigBean.jbiEnabled}"
>> target="main"
>> text="$resource{i18n.tree.jbi.deployments}"
>> toolTip="$resource{i18n.tree.jbi.deployments.toolTip}"
>> treeAdaptorClass="com.sun.jbi.jsf.util.JBIHookTreeAdaptor"
>> treeAdaptorListType="deployments"
>> url="/jbi/pe/deployments.jsf">
>> <facet name="image">
>> <iconHyperlink id="saLink" icon="TREE_FOLDER"
>> url="/jbi/pe/deployments.jsf" target="main" border="0"
>> immediate="true" />
>> </facet>
>> </dynamicTreeNode>
>>
>>
>>
>> Advantages:
>>
>> * JSF is abstracted (easier for non-jsf developers)
>> * Abstraction allows different UI / Themes to be rendered w/o too
>> much difficulty
>> * Code generation necessary will help effort to dynamically
>> generate UI
>> * Content is kept out of configuration
>> * Leverage existing ConfigParser + other HK2 concepts
>>
>> Disadvantages:
>>
>> * Much slower to migrate existing GUI application from v2 -> v3
>> * Many design details need to be solved before significant
>> development can begin (xml format, etc)
>> * Cannot leverage existing JSF user-base to extend admin console
>>
>> Requires:
>>
>> * Converting significant (possibly all) of current GUI application
>>
>>
>> *#4) Java-based integration*
>>
>> I won't show examples here... but this would use @annotations in java
>> files to define the same data as above (like @TreeNode annotations,
>> etc.). All meta-data would need to exist in java code or annotations.
>>
>> Advantages:
>>
>> * Easy for non-gui developers
>> * Perhaps is a basis for code-gen'd approach
>> * May be possible to combine this approach with any of the above
>> solutions.
>> * JSF is abstracted (easier for non-jsf developers)
>> * Abstraction allows different UI / Themes to be rendered w/o too
>> much difficulty
>> * Leverage existing @Service / @Contract annotations that
>> developers are familiar with.
>>
>> Disadvantages:
>>
>> * Much slower to migrate existing GUI application from v2 -> v3
>> * Unnatural to GUI developers
>> * GUI-specific content may be needed in source code where it
>> doesn't really belong (image names, etc)
>> * Many design details need to be solved before significant
>> development can begin
>>
>> Requires:
>>
>> * Would almost certainly require a combination of one of the other
>> options to be feasible. Disadvantages mostly go away if
>> combined with another option b/c developers have choices.
>>
>>
>> I'm sure there are countless other ways to approach this, these are
>> just the ones that come to mind right now. If anyone has other
>> suggestions, now is the time for us to consider them. :) We need to
>> be mindful of the amount of development time we have an the other
>> features we'd like to implement as well.
>>
>> Thanks!
>>
>> Ken
>>
>>
>> Kohsuke Kawaguchi wrote:
>>> Nazrul Islam wrote:
>>>> We will meet tomorrow (Tuesday, 1/22) at 11 am PST. Kohsuke will
>>>> talk about HK2 and how it relates to administration. Slides will be
>>>> sent out before the meeting.
>>>
>>> Slides attached.
>>>
>>>>
>>>> Agenda
>>>> HK2
>>>>
>>>> Conf Number
>>>> Toll Free: (866) 230-6968
>>>> Int'l Access: (865) 544-7856
>>>> Access Code: 3846234
>>>>
>>>> Conf Room Peter Pan's Flight
>>>> SCA 12 Room 3130
>>>>
>>>
>>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: admin-unsubscribe_at_glassfish.dev.java.net For
>> additional commands, e-mail: admin-help_at_glassfish.dev.java.net


-- 
Kohsuke Kawaguchi
Sun Microsystems                   kohsuke.kawaguchi_at_sun.com