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

With the new release of JDeveloper 11gR2, an extension that was written for a previous version of JDeveloper will no longer work.  There are a few changes that must be made to get things working again.  As with all development tasks, the work required can range from the very simple to extremely complex.  In this post, I'll cover the basics.  It should get everyone started in the right direction at least.

Your extension migration will follow these rough steps:

  1. Open your existing project in the 11.1.2 workspace
  2. Look at your existing extension and determine how it is integrated into the IDE. (e.g. Menu item, Wizard, etc.)
  3. If the integration point is coded in the Addin.initialize method, pull this out and replace it as a trigger-hook in the extension.xml file 
  4. If the menu or wizard hooks are already in use in the extension.xml file, move them into the trigger-hooks section. 
  5. Create an Action and controller class that will call the Addin.initialize() method when the action is called 
  6. Changes to the extension.xml file in regards to Classpath and dependencies will also have to be addressed 
  7. Make and Deploy to Target Platform to generate the manifest.mf file.

Open a copy of the workspace/project

NOTE: Make sure you are opening a copy of your extension source and not the original. This step can not be undone.

Make a copy of your existing extension source code and place it in a new directory that can be opened in the 11gR2 IDE.  Once you open the project, the IDE will ask to do some migration tasks that will bring the project and application files up-to-date with this version of the IDE.

How does the extension get initialized?

If your extension is already using a menu-hook, wizard, or context-menu-hook, in the extension.xml file for integrating with the GUI, you are in pretty good shape and there are only a few things that need to be changed to get things going again.

If you are using the Addin.initialize() method to register all of your menus, etc. then there is a little more work to be done.  It is the plan going forward, to completely remove the Addin.initialize() method and move everything to declarative hooks in the extension.xml or manifest.mf files.

I'll cover both situations in this blog topic, with Part One covering the non-Addin.initialize case, and Part Two extending to cover the rest.

Let's start with the SDK Sample project, "FirstSample".

When we look at this project we can see that none of the classes are extending the Addin class. We can also see that the menu setup is already being done declaratively in the extension.xml file.  This should make for a fairly simple migration.

I've made a copy of the FirstSample directory and placed it inside of another Application that I created in the 11gR2 version of the IDE.

When I open the project now, it brings up a migration wizard that looks like this.


I'll go ahead and just accept the defaults on the next couple of pages, then click on Finish.  The resulting dialog will look something like this.


 This process gets a few of the housekeeping things taken care of for the project itself.  It doesn't do anything to the source code of our project though.  That will remain the same.

Since we have already determined that we are not using any classes that extend the Addin class, we will only need to work with the extension.xml file.  I'll work through the file from top to bottom and show you what needs to get updated and how to go about doing it.

Classpaths


The <Classpaths> element has been deprecated in this release.  If it's in the extension.xml, it will just be ignored.  It has been replaced by a new element called <Required-Bundles>. The easiest way to make sure you are getting the proper bundle name when making these changes, is to use the Visual Editor for the extension.xml file.

Click on the Overview tab at the bottom of the editor window. 

Then click on the Dependencies menu.  It will look like this.


You can still see the entries that you currently have in your Classpaths element. We'll use these to get what we want in the Required-Bundles section.

Click on the + sign to the right of the Required Bundles section.  A dialog will popup with a list of all the available bundles. In the search field at the top of this dialog, type in the name of the first library that you currently have in classpaths.  "javatools" in this case.  This will narrow the list down to something that you can more easily select from. Go ahead and select the oracle.javatools bundle from the list. HINT:  Look at the slightly grayed out name under the jar files path.  This is the bundle name.  It will look like this when you're done.


 Repeat the steps above for the "oicons" bundle as well.

Once you have both of these added as Required Bundles, you can highlight the name of each Classpath entry, and then click the big red X on the right side of that section to remove this entry from the extension.xml file.


Clicking on the Source tab at the bottom of the editor, will get us back to the source code and the new entries should looks something like this


Go ahead and delete the remaining <classpath/> element from the file.  It will stop you from getting a warning at runtime.

Trigger-hooks

 Next we are going to add the new trigger-hooks section to the extension.xml file.  This is what allows us to use lazy loading with our extensions.  An extension is not loaded until a trigger is hit that tells the IDE that you want to use this functionality, so load it up.

Once you've done this a few times, you can simply cut and paste code from other extensions that you have already migrated, but I want to show a little tool that can help when you're not quite sure where to start.

If you right-click on the <extension> element in the Structure window (lower right side of the IDE by default) you will see an option to "Insert Inside extension".  Select that option and go all the way to the bottom of the submenu and select "trigger-hooks".

Now right-click again, but on the trigger-hooks element this time, and insert a "trigger-hook" inside the trigger-hooks element.

You will notice that it places a nice clean <trigger-hook /> element in between the open and close <trigger-hooks> tags.  We need to change this to be an open and close tag instead of just the one tag.  If you delete the "/" from the trigger-hooks tag and then hit enter and type "</ " you will notice that the IDE will enter the close tag for you. The end result should look like this


You can see that this would have been a lot easier to just cut and paste in, but I wanted to show you that we do have a tool for working with the schema. We'll use this same tool a little later to add a Controller element which has a few more required parameters.

Actions

Now that we have the trigger-hooks structure in place, we can start moving some of our old elements up into this new area.  Since the Actions element is what most everything else references, let's move it in first.  Simply cut and paste the existing actions element from the <hooks> section up to the new <trigger-hooks> section.


We need to add an xml namespace to the <actions> element now.  The easiest way to do this is to click inside the <actions> tag just after the word "actions". Enter a space and then type " xmlns=" ". After you type the first " after the equal sign, a code completion pulldown should show up and give you a list of available namespaces to select from.  In this case, scroll down until you find, " http://xmlns.oracle.com/jdeveloper/1013/extension  ".  Add the close " and you're done.

Controllers are now their own element in the extension.xml file, so we will delete the existing <controller-class> element from the actions element. The resulting actions element should now look like this


Controllers

Controllers are a new element in the extension.xml file.  We're going to go back to the schema helper tool to add in our new controllers element.

Right-click on the <triggers> element in the Structure window and select "Insert Inside triggers".  Click Browse and scroll down the list until you find "Controllers". Click OK and then right-click on the new controllers element and follow the same steps to insert a controller element inside of the controllers. This is going to open a dialog asking you to enter the class for the controller.  If you start typing the package name for your controller, code completion will kick in and help you find the existing controller class.  It will look like this


 For this example, work your way down to the SimpleController class and click OK.

Let's keep adding the required elements to our new <controller> element.  Right-click on the controller element again, and insert an <update-rules> element, and then insert an <update-rule> element inside of that.  You will be asked for the "rule *: " when you insert the <update-rule>.  For now, just type in "always-enabled" for the rule.  I'll talk more about the new Rules system in another post, very soon.  The last thing to add is the <action> element.  Follow the same steps to insert the <action> element inside of the <update-rule> element.

You will be asked for the action id and label when you insert the action element.  You can copy the action id from the action element that we just added above. For this example it will be: "oracle.ide.extsamples.first.invokeAction"

You can set the label for your controller here as well, but it's not required.  Since we already have a label in our Action, I'm just going to leave this blank.  The final Controllers element should look like this


Context Menus

 Context menus are next in the existing extension.xml file, so lets take those on next.  The context menu element is a little different in the new release. Here is what the original looks like


We're going to use the xml schema tool again to get the new structure setup.

Right-click on the triggers element and "insert inside triggers".  Click Browse, then select the Context-menus-hook.  Enter "always-enabled" for the rule type when prompted.

Now right-click on the new context-menus-hook element, and insert a "site" element inside of this one.  You will be prompted for the "idref" for the context menus that you want to add.  In the original we had to created three different elements to cover all three of the main context menus.  Here we can enter all three as a comma separated list. 
Enter, "navigator, editor, explorer" and click OK.

Right-click one more time on the context-menu-hook, and insert an extension-listener element this time, inside the context-menu-hook element. Set the class name to be the same as what you had in the original elements. In this example, it would be, "oracle.ide.extsamples.firstsample.SimpleContextMenuListener"

The <extension-listener> element is optional. In this case, it works great because it just replaces the listener element that was already being used.  If you context-menu-hook uses the menu element instead of a listener-class element, do the steps below instead of adding the extension-listener element.

Now right-click on the menu element and insert inside of it, a section element. You can set the ID for this section to be anything you like. Once you have the section element created, insert an "item" element inside of it.  Set the "action-ref" value to the action id that we set above.  For this example it is: "oracle.ide.extsamples.first.invokeAction"

The new context-menu-hook element should now look like this id you used the <menu> element

 and like this if you used the <extension-listener> element

Notice that I still had to add an empty <menu/> element, since it is a required element.


Gallery

The gallery element hasn't changed that much.  Copy and paste the original from the <hooks> element into the new <triggers> element.


 We only need to make a couple of changes to this element. We need to add an xml namespace to the gallery tag. Follow the same steps as above, where you clicked inside the tag, just after the name, enter a space, then type, "xmlns=" " when the code completion list comes up this time, select the same namespace as before,
"http://xmlns.oracle.com/jdeveloper/1013/extension"

Now we need to add a rule parameter to the <item> tag.  Type inside the tag, and add, " rule="always-enabled".  The new item tag will look like: <item rule="always-enabled">

We also want to add an <icon> element to the gallery element now.  This is pretty simple.  Just add the line:

<icon>${OracleIcons.LABEL}</icon>

 Everything else should stay the same.  The new gallery element will look like

Menus and Toolbars

The <menu-hooks> element is even easier then the Gallery hook.  Copy and paste the entire <menu-hooks> (including menu and toolbar hooks) element into the <triggers> element.

All we have to do is add an xml namespace to the <menu-hooks> tag.  Set this to " xmlns="http://jcp.org/jsr/198/extension-manifest" "

Once you have all of these elements moved from the Hooks element to the Triggers element, the only thing left in the Hooks section should be the <features-hook>. This can be left where it is.  The <hooks> element does still get called by the extension framework.  It is called as the extension is loaded.  The best way to decided if something belongs in the <triggers-hooks> element or the <hooks> element is to think about when that information needs to be available to the IDE.  If it's something that has to show up before the extension is actually loaded, then it should be in the <trigger-hooks> element.  Otherwise, it's fine to leave it where it is.

Conclusion...

That should do it for migrating this extension.  To test everything and make sure it really does work, you need to follow these three steps.

1) Build the extension
This is an obvious step and of course it should compile without any errors.

2) Deploy to Target Platform
This is a new step that must be run every time before you can perform the "Run Extension" menu option.  It builds the manifest.mf file and packages everything properly. Rick-click on your project and select this from the menu down in the Extensions section.

3) Click on Run Extension
This performs the same as it always has. It will open another instance of the IDE with your extension installed and, hopefully, running correctly.

More...

In Part Two I finish the migration steps by showing how to handle migrating an extension that extends the Addin class. You will still need to do all of the work that we have just shown above, but there is a little more work to do as well.

Comment are always welcome, and encouraged.  Everyone learns more when a good conversation is started!


Comments:

Hi!

In my pmd extension I need the classpath entries for referencing classes from pmd, which are delivered with the plugin. These are not available as bundle before, so how should this migrated to a bundle?

Kind regards

Posted by guest on June 16, 2011 at 04:22 AM PDT #

Great to hear you're working on an update to PMD.

To add external libraries, do the following
1) Add an MANIFEST.MF file to your project in the same location as the extension.xml
2) Add the default 3 lines to the file of:
Manifest-Version: 1.0
Bundle-ClassPath: .
<blank line>
3) Add your libraries to the Bundle-Classpath line with the following syntax

external:$ORACLE_HOME$/jdeveloper/mydir/mylib/myjar.jar

Using the default above, and this example line, the Bundle-Classpath would look like.

Bundle-Classpath: ., external:$ORACLE_HOME$/jdeveloper/mydir/mylib/myjar.jar

If you find that the MANIFEST.MF is not being merged after you do the "Deploy to Target Platform", do the following to force the merge.

1) Go to project properties and click on the Deployment section. Add the path to your new MANIFEST.MF file to the "Add additional manifest files..." section.

You usually do not need to do the step above, but I have had people tell me that the merge isn't happening for some reason, and this fixes it in those cases.

Posted by guest on June 16, 2011 at 04:46 AM PDT #

I'm build a extension using Addin.initialize to provide extra functionality to menus, the extension integrates a Java Swing Menu with Ubuntu Unity Menus, and I'm not use menu, context menu, or another feature.

The extension in JDeveloper 11gR1 is this:

@RegisteredByExtension("org.jdev.java.ayatana")
final class AyatanaAddin implements Addin {
public void initialize() {
JFrame frame = (JFrame)Ide.getMainWindow();
ApplicationMenu.tryInstall(frame);
}
}

And thats all, how migrate this code to JDeveloper 11gR2, there are any startup listener using trigger-hook?

Posted by Jared on April 23, 2012 at 06:22 PM PDT #

Hi Jared,

No, there is not a trigger-hook for on startup. That is what we are trying to get away from with the lazy loading in OSGi. You can not just load an extension when the IDE is started.

You will need to create a menu hook of some kind to load your extension the first time. Once a developer has your extension loaded, it will be remembered so that it will come up automatically each time the IDE is started with that project or application open.

HTH,

--jb

Posted by John 'JB' Brock on April 30, 2012 at 10:16 AM PDT #

its really good forum.. thanks...i am able to migrate my extension but i am facing some issues.. could you please tell me i have log4j.jar and i need to use that how can i add that in extension.xml because when i am trying to add from resource bundle it showing only available jars in Oracle/lib folder not other... please suggest me the solution

Posted by guest on April 11, 2013 at 07:18 AM PDT #

Take a look at the blog post about adding external dependencies.
https://blogs.oracle.com/jdevextensions/entry/adding_exteneral_jars_to_an

That should get you going again.

--jb

Posted by John "JB" Brock on April 12, 2013 at 09:24 AM PDT #

Thanks for the reply one more problem i am facing when i am running extension its opening new Jdev extension and my changes gets reflected there but when i am exporting jar and try to use that jar on different machine that time my changes are not reflected i do not understand what could be the problem :( please share me if there are some steps. for exporting jar or something else

Posted by guest on April 22, 2013 at 03:57 AM PDT #

I'm not sure what you mean by "exporting jar". Are you trying to deploy the extension to another JDeveloper instance?

You will want to look at this blog post about packaging an extension for distribution and use by others.

https://blogs.oracle.com/jdevextensions/entry/working_with_jdeveloper_update_centers_and_bundlexml

Posted by John 'JB' Brock on April 22, 2013 at 07:42 AM PDT #

I would be happy if you could help me:-)

I had developed an extension for Oracle SQL Developer 3 version with the previous JDev versions. Now I have starting migration of my extension... Focusing the databases context menus - I have in my extension context menu items added to the existing oracle explorer various objects as connection, table etc. context menu: In my old extension, I had a contextmenu xml file which I have define the various menu items under the specific location by specifing: etc. and the registration I have done in the "initializeAddin" by: Xmlbasedbjectsaction.registercontextmenus (Which currently is obselete).

In the 12 c version, I am trying to migrate the changes: In the extension.xml file I have added the action->controller->contex-menuhook under the trigger-hook section as described - How can I define the context menu items to be added to the existing oracle connection ide database context menu? If you can provide me a working example it would be wonderful.
I assume the namespace of the sql dev context menu should not be the jcp.org etc... and the site id-ref would be also suited to the db nav??
Thanks a lot in advance!!
Freydie

Posted by Freydie on February 24, 2014 at 05:24 PM PST #

Hi Freydie,

While SQL Dev is built on top of JDeveloper at it's core, the user interface can be different when it comes to extending it. Somethings work the same, but there is a lot that is different. I'm sorry but I am not an expert at creating extensions for SQL Developer, and have only attempted it once, without a lot of success myself.

I would take a look over in the SQL Developer forums. This looks like a good place to start:
https://community.oracle.com/message/9831246#9831246

Posted by John 'JB' Brock on February 24, 2014 at 05:56 PM PST #

Thank you John - Will look into those forums

Posted by Freydie on February 25, 2014 at 12:14 PM PST #

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