Migrating an Existing Extension to JDeveloper 11gR2 -- Part Two

We covered the basics of how to migrate an extension that does not use the Addin.initialize() method, in Part One of this topic. If you haven't taken a look at that yet, I strongly recommend that you do.

Quick review

With the release of JDeveloper 11g R2, the extension framework is now based on OSGi.  Because of this, we no longer load all of the extensions at the same time, at the startup of the IDE.  We now use something called Lazy Loading which only loads extensions when they are needed. Because Addin.initialize() is no longer called at IDE startup, you have to think a little more carefully about of how your extension integrates into the IDE. You can't just dump everything out there and have it ready to go.

I'm going to use the Extension SDK sample project, "OpenNodes" for this migration example.


A different point of view

The first thing we need to think about, is what user interface element can be used to trigger the loading of the rest of the extension. When we open the OpenNodesAddin class, which extends Addin, we see that there are two different things going on in the initialize() method.

A new factory object is being created and a call to a method called installViewMenu, which does exactly that.  It installs a menu item into the View menu. This is exactly what we are looking for.

If we move the functionality of this method to be done declaratively in the extension.xml file's trigger-hooks section, we will be able to show the menu item in the View menu, without actually loading any of the other code in the extension.  It will not get completely initialized until the menu item is selected. Go ahead and comment out the call to the installViewMenu() method and save the file.

The existing extension.xml file also contains an action element which will need to be migrated.  You can refer back to Part One for information on how to modify the action element and add the now required controller element as well.

We'll focus on the installViewMenu() method and how we will migrate it's functionality over to a menu element in the extension.xml file.  Here is what the existing method looks like


This is a pretty simple method that adds a menu item to the View menu on the IDE main menubar. It calls the only action that we have in the extension.xml file already. It doesn't have anything in the method that defines where the menu item is supposed to be placed within the View menu itself.  We can just do the same thing and let the IDE place the menu item in the default location if we like.


Let's move over to the extension.xml file now and add our menu element to the triggers section of the file. For this example, I have already gone ahead and done the migration of the action element, as well as the changes to the reuired-bundles element.

I'm going to go ahead and add the <menu-hook> element to the bottom of the <triggers> element, right after the new <controllers> element that we added.

The <menu-hook> element has one required argument of "xmlns".  We'll set this to "http://jcp.org/jsr/198/extension-manifest"

Once you have the menu-hook element started, you can use the xml schema tool in the Structure window, just as we described in Part One of this topic. We will need to add the following elements to finish the menu-hook section.


If you are not sure what values to use for the <menubar> id and <menu> id, you can refer back to a blog post I did early in 2011 about how to work with declarative menus in jdeveloper extensions.

The new trigger-hooks section is going to look like this when it's done.


We should be able to test the new version of the extension now, by doing the steps of:

-- Build
-- Deploy to target platform
-- Run Extension

The "Deploy to Target Platform" step is required in 11gR2 before you try the "Run Extension" feature.  This builds the OSGi bundle so that it can be deployed properly.

Cleaning things up

Once you run the new version, you should come across two things.

1) There is a warning telling you that "registerDockableFactory" has been deprecated, after you do the compile (I'm doing a rebuild when I see this)

2) When you actually run the extension, a Warning will be thrown telling you that the <feature> hook doesn't have a corresponding <feature-member>.

While everything will run fine with these warnings in place, lets go ahead and clean things up.

To get rid of the runtime warning, let's add a <feature-member> element just before we start the <trigger-hooks> section.

The registerDockableFactory() method is being replaced with a trigger-hook.  You can add this to the triggers element using the schema editor in the Structures window.  The class name and id will be required.

The result will look like this.

The last thing to do, is go into the OpenNodesDockableFactory class and comment out the method that does the existing registration.  Leave the ID variable declaration though.  That's needed by other parts of the code.


Now if we rebuild, deploy, and run the extension, everything should work without any warnings or errors.

Conclusion

By moving the GUI elements out of the Addin.initialize() method, we can display the connections that our extension requires for the user to enable the full functionality and start usng the extension. Once the trigger is hit, the IDE will call the Addin.initialize() method and do the rest of the loading of the extension.

There may still be cases where an extension needs to load, but doesn't have a GUI element to use as a trigger.  In those cases, there is usually something else that is being added to the IDE by the extension, that can be used as a trigger.  Take a look at the Trigger Hooks Wiki for a list of trigger-hooks provided by the IDE, and some more information about each of them.

As usual...  Comments, Comments, Comments.  Toss out your experiences and questions for others to learn from. All are welcome.

Comments:

Looking for information on template-hook

Posted by guest on December 15, 2011 at 06:15 AM PST #

In regards to the difference between 11gR1 and 11gR2? Or just info about template-hook in general?

The only difference is that you place the <template-hook> element in the <trigger-hook> section of an R2 extension.xml file and you add the namespace to the opening element.

<template-hook xmlns="http://xmlns.oracle.com/ide/extension">

Otherwise the elements are exactly the same in R1 and R2.

Let me know if this helps or not.

--jb

Posted by John 'JB' Brock on December 15, 2011 at 06:31 AM PST #

I have migrated an extension from R1 to R2. It works fine on my PC. When I install this extension to another PC, I got this error: java.lang.NoClassDefFoundError: oracle/ide/controller/Controller
(I use some classes from oracle.ide.jar which is in path $ORACLE_HOME$/jdeveloper/ide/extensions/ - I have this bundle in the extension.xml file in extension dependencies)
I couldn't find any reason for that. Do you have any suggestion?
Thanks

Posted by Vladimir on April 05, 2012 at 09:14 PM PDT #

This is most likely caused by a required dependency not being added to the MANIFEST.MF file.

Take a look at this blog post to see how to check if the files are being listed properly
https://blogs.oracle.com/jdevextensions/entry/adding_exteneral_jars_to_an

If this doesn't work, or doesn't make sense, please contact me directly via email (john<dot>brock<AT>oracle.com and I'll be happy to help work this out with you.

Posted by guest on April 06, 2012 at 02:51 AM PDT #

IS there a way to load the extension at IDE startup? I noticed that there is a Ballon project in the extension samples that has no trigger-hooks and is loaded at IDE startup. Extensions log says that it was triggered and reason is "Marked to reload at startup" but I don't understand how it is achieved. I have also seen the same question (unanswered) here: https://forums.oracle.com/forums/thread.jspa?messageID=10706474

Posted by Aleksei Sosnovski on February 04, 2013 at 05:13 AM PST #

Hi Aleksei,

No, there is not a trigger-hook to load an extension at Startup. That would defeat the entire purpose of lazy loading of extensions. Once a developer has loaded your extension the first time, it will continue to be loaded at startup if the project that references it, is still open.

The Balloon example is an odd case in that it's actually a child of a larger extension that was already loaded. It makes it look like it's loading at startup, but it's not.

Posted by John 'JB' Brock on February 04, 2013 at 06:41 AM PST #

Thanks for the prompt reply.

If there is no out-of-the-box way to load the extension at startup, I will have to find an alternative.

There are certain features that ideally require the extension to be loaded at startup. Among many other things, it has to register a custom JavaOptionProvider. I see multiple ways to do it:
- Load the extension when (actually before) a Java process is started. It also includes starting Weblogic, at least the integrated one. Since other custom extensions may start Java processes, catching this event might be a problem.
- Load the extension when a project has Java technology. Not the best solution because AFAIK one can start integrated Weblogic without opening any projects, but it should be sufficient.
- Create a custom trigger hook that would load the extension at startup.

Which of the above solutions sounds most reasonable? And how this solution can be implemented? Unfortunately documentation on technology scope hook and custom hooks is insufficient, at least for somebody who has as little experience with JDeveloper as I do.

Posted by guest on February 04, 2013 at 11:26 PM PST #

I am migrating an extension from 11gR1 to 12c(12.1.2). I am not able to make code template work on JDev12.1.2.

In 11.1.1.5 we have the code template file under meta-inf folder and in the extension.xml file we have the following entry under hook
<code-template-hook xmlns="http://xmlns.oracle.com/ide/extension">
<templates-url>/meta-inf/code-templates.xml</templates-url>
</code-template-hook>

For 12c I am doing the same other than adding the code-template-hook under triggers section. But its not working. Is there something more i need to do ?

Posted by Apurba on July 24, 2013 at 08:13 AM PDT #

Hi Apurba, questions like this are probably best asked and answered in the forums instead of in comments of the blog.

I would re-ask this question over at:
https://forums.oracle.com/community/developer/english/development_tools/application_development_in_java/jdeveloper_and_adf

While you're moving over there though, I would ask first if the extension loads at all? Placing this tag in the triggers section is not going to actually trigger the extension load. What are you using as a trigger-hook?

Posted by John 'JB' Brock on July 24, 2013 at 08:32 AM PDT #

I have added a Tools menu item via menu bar hook which is used to load and initialize the custom extension I am migrating for 12.1.2. Upon initializing the extension creates a custom workspace and add it to the jdeveloper content pane.

Till now I was running the extension in debug mode from Jdeveloper and everything was working fine. But if I just copy the extension jar to Jdeveloper 12.1.2 "jdeveloper\jdev\extensions" folder the tools menu item is not added which I am using to load and initialize the extension.

Posted by guest on July 25, 2013 at 07:21 AM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

profile image
My name is John 'JB' Brock.
This Blog will focus on tips and tricks for working with the JDeveloper Extension SDK.
I hope to bring clarity to some of the mysteries around developing extensions for JDeveloper.


Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today