August 23, 2008

Creating custom menu in Documentum 6

WDK of Documentum 6 brings in come major enhancement for developers. The new library is Section 508 compliant and has also undergone user testing for accessibility and usability by the NFB (National Federation for the Blind). The list of new features is a big list including change to UI like right-click context menus, XML-based fixed menus that can be modified or extended, Configurable keyboard shortcuts etc. In this post we will see how to add a menu to the menu bar using configuration elements rather than extending menubar component.

In previous versions on WDK, you would have extended the menubar component and placed the xml in custom/config folder. You would also move the menubar.jsp with your new menu and menu items. In D6, things are little different. Let me quote from WDK tutorial PDF:
In earlier versions of the Web Development Kit, you would extend and override the configuration information files that come with the product as shipped. That approach still works. However, in Version 6, you have the option of modifying the user interface by adding, removing, or replacing individual configuration elements.
And this is exactly what we are going to do today. The concept of configuration elements is a great advantage to developers. By just changing XMLs you can modify the component. There is no need to extend each component for a minor change. This concept also makes the customizations more manageable and developer friendly.

WDK introduces component modification instead of extending it. To modify a specific component all you have to do is create a XML file in custom/config and specify the component you need to modify using modifies attribute of component element. Have a look at the below XML where I simply add a new menu item in tool menu of the webtop:
<config>
<scope>
<menuconfig modifies="menubar_tools_menu:webcomponent/config/library/menubar/menubar_component.xml">
<insert path="menu[name=tools_menu]">
<actionmenuitem dynamic = "genericnoselect"
name = "hello_world_menu_item"
id = "hello_world_menu_item"
value = "Hello World"
action = "hello_world_action"
showifinvalid = "true"/>
</insert>
</menuconfig>
</scope>
</config>
The XML is simple and clean. In earlier versions, you will have used the “extends” attribute and specified the component you are extending. Here we just specify the component you want to modify and specify the section (in the above case menubar_tools_menu). WDK offers five different configuration elements: insert, insertafter, insertbefore, replace and remove. You can use these elements to modify any component.

An important change to notice is the way how menu component works. If you open menubar_component.xml in /webcomponent/config/library/menubar you will notice that all the menu and menu items are declared as part of the component.In previous versions, this would have been part of the JSP. Also notice each menu is defined by the tag menuconfig. These entire menus are declared in menuconfigids element as shown below:
<menuconfigids>
<id>menubar_file_menu</id>
<id>menubar_edit_menu</id>
<id>menubar_view_menu</id>
<id>menubar_tools_menu</id>
</menuconfigids>
To add a new menu, we will have to modify the menuconfigids and our custom menu into it. Let’s see how we will insert a new menu into menuconfigids:
<component modifies="menubar:webcomponent/config/library/menubar/menubar_component.xml">
<replace path="menuconfigids">
<menuconfigids>
<id>menubar_file_menu</id>
<id>menubar_tools_menu</id>
<id>my_tools_menu</id>
</menuconfigids>
</replace>
</component>
And to define the menu and one menu item:
<menuconfig id="my_tools_menu">
<menu name="Level1" value="Level One">
<actionmenuitem dynamic = "genericnoselect"
name = "hello_world_menu_itemx"
id = "hello_world_menu_itemx"
value = "Hello World"
action = "hello_world_action"
showifinvalid = "true"/>
</menu>
</menuconfig>
So finally we have a single XML containing the above two fragments:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<config version="1.0">
<scope>
<menuconfig id="my_tools_menu">
<menu name="Level1" value="Level One">
<actionmenuitem dynamic = "genericnoselect"
name = "hello_world_menu_itemx"
id = "hello_world_menu_itemx"
value = "Hello World1"
action = "hello_world_action"
showifinvalid = "true"/>
</menu>
</menuconfig>
<component modifies="menubar:webcomponent/config/library/menubar/menubar_component.xml">
<replace path="menuconfigids">
<menuconfigids>
<id>menubar_file_menu</id>
<id>menubar_tools_menu</id>
<id>my_tools_menu</id>
</menuconfigids>
</replace>
</component>
</scope>
</config>
A simple WDK refresh will make your menu appear on webtop! That's all and it's time for a hot tea :)

1 comment :

SAURABH said...

Have you check this coding?
I am applying the same thing in my custom menubar_component.xml which is in custom/config/webcomponent/menubar_component.xml
It is returning me the error:
13:39:24,125 ERROR [main] com.documentum.web.common.Trace - An error occurred during application intialization : path is requ
ired for modification action: (D:\webtop for customization\webtop/custom/config/webcomponent/menubar_component.xml)config[ver
sion=1.0].scope[application=custom,version=latest].component[modifies=menubar:webcomponent/config/library/menubar/menubar_com
ponent.xml].desc
java.lang.IllegalStateException: path is required for modification action: (D:\webtop for customization\webtop/custom/config/
webcomponent/menubar_component.xml)config[version=1.0].scope[application=custom,version=latest].component[modifies=menubar:we
bcomponent/config/library/menubar/menubar_component.xml].desc
at com.documentum.web.formext.config.ConfigElement.applyModification(ConfigElement.java:847)
at com.documentum.web.formext.config.ConfigService.processModifications(ConfigService.java:1137)
at com.documentum.web.formext.config.ConfigService.initialiseApp(ConfigService.java:952)
at com.documentum.web.formext.config.ConfigService.(ConfigService.java:787)
at com.documentum.web.formext.config.ConfigService.getInstance(ConfigService.java:59)
at com.documentum.web.formext.config.ConfigService.getConfigLookup(ConfigService.java:75)
at com.documentum.web.env.NotificationManager.getListenersFromConfigFile(NotificationManager.java:315)
at com.documentum.web.env.NotificationManager.getListerners(NotificationManager.java:303)
at com.documentum.web.env.NotificationManager.initializeListenerMap(NotificationManager.java:362)
at com.documentum.web.env.NotificationManager.doApplicationStart(NotificationManager.java:206)
at com.documentum.web.env.NotificationManager.contextInitialized(NotificationManager.java:111)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4350)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:626)
at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:553)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:488)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1147)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)

Jan 16, 2009 1:39:25 PM org.apache.catalina.core.StandardContext start
SEVERE: Error listenerStart
Jan 16, 2009 1:39:49 PM org.apache.catalina.core.StandardContext start
SEVERE: Context [/msmtesting] startup failed due to previous errors
Jan 16, 2009 1:39:49 PM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive BravaServer.war
Jan 16, 2009 1:39:49 PM org.apache.catalina.core.StandardContext addApplicationListener
INFO: The listener "com.infograph.httpserver.ApplicationTimerListener" is already configured for this context. The duplicate
definition has been ignored.
Jan 16, 2009 1:39:50 PM com.infograph.httpserver.ServerConfiguration addLogHandlers
INFO: Loggers Initialized.
Jan 16, 2009 1:39:50 PM org.apache.catalina.loader.WebappClassLoader loadClass
INFO: Illegal access: this web application instance has been stopped already. Could not load org.apache.xerces.impl.dtd.XMLN
otationDecl. The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to
terminate the thread which caused the illegal access, and has no functional impact.
java.lang.IllegalStateException
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1246)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1206)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
at org.apache.xerces.impl.dtd.DTDGrammar.notationDecl(Unknown Source)
at org.apache.xerces.impl.dtd.XMLDTDProcessor.notationDecl(Unknown Source)
at org.apache.xerces.impl.XMLDTDScannerImpl.scanNotationDecl(Unknown Source)
at org.apache.xerces.impl.XMLDTDScannerImpl.scanDecls(Unknown Source)
at org.apache.xerces.impl.XMLDTDScannerImpl.scanDTDExternalSubset(Unknown Source)
at org.apache.xerces.impl.XMLDocumentScannerImpl$DTDDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at org.apache.tomcat.util.digester.Digester.parse(Digester.java:1644)
at org.apache.catalina.startup.TldConfig.tldScanStream(TldConfig.java:518)
at org.apache.catalina.startup.TldConfig.tldScanJar(TldConfig.java:476)
at org.apache.catalina.startup.TldConfig.execute(TldConfig.java:301)
at org.apache.catalina.core.StandardContext.processTlds(StandardContext.java:4441)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4248)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:924)
at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:887)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1147)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Jan 16, 2009 1:39:50 PM org.apache.catalina.startup.HostConfig deployDirectory
SEVERE: Error deploying web application directory da
java.lang.NoClassDefFoundError: org/apache/xerces/impl/dtd/XMLNotationDecl
at org.apache.xerces.impl.dtd.DTDGrammar.notationDecl(Unknown Source)
at org.apache.xerces.impl.dtd.XMLDTDProcessor.notationDecl(Unknown Source)
at org.apache.xerces.impl.XMLDTDScannerImpl.scanNotationDecl(Unknown Source)
at org.apache.xerces.impl.XMLDTDScannerImpl.scanDecls(Unknown Source)
at org.apache.xerces.impl.XMLDTDScannerImpl.scanDTDExternalSubset(Unknown Source)
at org.apache.xerces.impl.XMLDocumentScannerImpl$DTDDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at org.apache.tomcat.util.digester.Digester.parse(Digester.java:1644)
at org.apache.catalina.startup.TldConfig.tldScanStream(TldConfig.java:518)
at org.apache.catalina.startup.TldConfig.tldScanJar(TldConfig.java:476)
at org.apache.catalina.startup.TldConfig.execute(TldConfig.java:301)
at org.apache.catalina.core.StandardContext.processTlds(StandardContext.java:4441)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4248)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:924)
at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:887)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1147)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Caused by: java.lang.ClassNotFoundException: org.apache.xerces.impl.dtd.XMLNotationDecl
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1360)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1206)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
... 40 more
Jan 16, 2009 1:39:50 PM org.apache.catalina.startup.HostConfig deployDirectory
SEVERE: Error deploying web application directory examples
java.lang.NoClassDefFoundError: org/apache/xerces/impl/dtd/XMLNotationDecl
at org.apache.xerces.impl.dtd.DTDGrammar.notationDecl(Unknown Source)
at org.apache.xerces.impl.dtd.XMLDTDProcessor.notationDecl(Unknown Source)
at org.apache.xerces.impl.XMLDTDScannerImpl.scanNotationDecl(Unknown Source)
at org.apache.xerces.impl.XMLDTDScannerImpl.scanDecls(Unknown Source)
at org.apache.xerces.impl.XMLDTDScannerImpl.scanDTDExternalSubset(Unknown Source)
at org.apache.xerces.impl.XMLDocumentScannerImpl$DTDDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at org.apache.tomcat.util.digester.Digester.parse(Digester.java:1644)
at org.apache.catalina.startup.TldConfig.tldScanStream(TldConfig.java:518)
at org.apache.catalina.startup.TldConfig.tldScanTld(TldConfig.java:555)
at org.apache.catalina.startup.TldConfig.execute(TldConfig.java:295)
at org.apache.catalina.core.StandardContext.processTlds(StandardContext.java:4441)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4248)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:924)
at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:887)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1147)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Exception in thread "Resource Housekeeper" java.lang.NullPointerException
at com.documentum.fc.common.DfLogger.getCurrentPrefix(DfLogger.java:516)
at com.documentum.fc.common.DfLogger.getLogger(DfLogger.java:383)
at com.documentum.fc.common.DfLogger.error(DfLogger.java:109)
at com.documentum.fc.internal.reshousekeeper.ResourceHousekeeper$1.run(ResourceHousekeeper.java:44)
Jan 16, 2009 1:39:51 PM org.apache.catalina.core.StandardContext addApplicationListener
INFO: The listener "com.documentum.web.env.NotificationManager" is already configured for this context. The duplicate definit
ion has been ignored.
Jan 16, 2009 1:40:05 PM org.apache.coyote.http11.Http11Protocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
Jan 16, 2009 1:40:05 PM org.apache.jk.common.ChannelSocket init
INFO: JK: ajp13 listening on /0.0.0.0:8009
Jan 16, 2009 1:40:05 PM org.apache.jk.server.JkMain start
INFO: Jk running ID=0 time=0/31 config=null
Jan 16, 2009 1:40:05 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 50107 ms
Jan 16, 2009 1:40:18 PM org.apache.catalina.loader.WebappClassLoader findResourceInternal
INFO: Illegal access: this web application instance has been stopped already. Could not load dfc.properties. The eventual f
ollowing stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which
caused the illegal access, and has no functional impact.
Exception in thread "Thread-2" java.lang.NullPointerException
at com.documentum.fc.common.DfLogger.getCurrentPrefix(DfLogger.java:516)
at com.documentum.fc.common.DfLogger.getLogger(DfLogger.java:383)
at com.documentum.fc.common.DfLogger.error(DfLogger.java:91)
at com.documentum.fc.common.impl.preferences.PreferencesManager.readPersistentProperties(PreferencesManager.java:320)

at com.documentum.fc.common.impl.preferences.PreferencesManager.(PreferencesManager.java:37)
at com.documentum.fc.common.DfPreferences.initialize(DfPreferences.java:79)
at com.documentum.fc.common.DfPreferences.getInstance(DfPreferences.java:58)
at com.documentum.fc.common.DfFileWatcher.getConfigCheckInterval(DfFileWatcher.java:24)
at com.documentum.fc.common.DfFileWatcher.run(DfFileWatcher.java:47)