Friday Oct 28, 2011

Adding files to an existing project

I've run into this question a few times now in the Jdeveloper forums and thought it would be a good topic for this blog.

There are multiple ways that you can add a file to a project in JDeveloper, but only one that will really get the file properly setup in the IDE framework.

NOTE: The code shown below will work in both 11gR1 and 11gR2.

Let's start by showing the entire code block and then breaking it down.


The first thing we have to do, is get the current project, so that we know where to write this new file to.  I'm running this chunk of code from the controller class of a Context Menu item that I created to show up in the Navigator.  This provides me with a context to work with and I can get the project with a simple getProject() call.

The most important thing to note in all of the file manipulation, is that we are NOT using the standard Java.io methods.  We are using URLFileSystem and URLFactory to do all of the work.  This makes sure that the file that we create is being integrated into the IDE framework properly.


A quick lesson in Navigator view and Directory structures

The Navigator window in the IDE, is not a representation of what is on the filesystem.  This is really important to understand. That Navigator is a representation of what is in your Application (.jws) and Project (.jpr) files.  There are many things in the filesystem that do not show up in the Navigator.  One thing in particular is an empty directory is filtered out and not shown at all. 

The Navigator also does it's own grouping of source files into a folder called Application Sources and other files located in non-source-path directories are grouped under a folder called Resources.

By default any files under the /src directory will be shown in the Application Sources folder of the Navigator window.

Here is a quick look at the CreateStructure sample project and how things look on the filesystem and in the navigator window.

Filesystem


Navigator

Notice how the directories that I created earlier (/src/test/name) do not show in the navigator window?

By default the navigator shows the directories under /src as the package id.  You can adjust how this is displayed by adjusting the package level value in the navigator display settings


Writing the file

Ok, back to the actual code now. You will see that I created a URL variable called path that points to the directory that I want to place the new file in.  I used the URLFileSystem method mkdirs() to make sure the directory is created before I try and place the file in it.  The nice thing about mkdir*s* versus mkdir is that it will create the entire path, including parent directories, if they don't already exist.

In the sample, I've just hardcoded the file name. You can get this from a dialog or whatever means you want. I then created a new URL using both the path and filename variables.

I then created a new TextNode to represent our new file, and I called a method that I wrote called writeDefaultText(). This just adds a comment to the top of our new file so that it's not empty.  The editor handles files with a little something in them better. I believe most folks that take the time to write an extension that adds a file, is going to seed that file with some pre-generated code anyway.

Here is a look at the writeDefaultText() method

After we have some content in the file we do sav of the file in it's own try / catch block. 


Updating the Navigator

Finally we need to update the Navigator window so that it displays our new file as part of the project.


Conclusion

While you can use the standard java.io classes to create the file on the filesystem, it's best to use the URLFileSystem methods provided by the IDE to do this.  It's really a pretty easy thing to do once you know the proper methods to use.

As always, don't hesitate to add your comments and experiences to the comments section so others can learn from your coding experiences as well.


Friday Sep 16, 2011

Find your way Home

I often find myself working in one extension.xml file, while I have another extension.xml file, from a different application, open as a reference.  When working with multiple applications open, you can get in a state where the file you're looking at in the editor, is not really located in the application that is shown in the Navigator. 

It can be confusing and a bit of a pain to have to select the application from the pulldown in the navigator and switch back and forth.

Well, you don't have to.  When you are in the editor for a specific file, just type Alt-Home and the Navigator will sync to whatever application and project that file is located in.  Quick and Easy!

 Hope this helps others as much as it has helped me.

Friday Sep 09, 2011

Cleaning up after yourself -- Deleting test extensions

When developing extensions, you often need to run the extension to test something, then make some changes, and run it again.  Often many times in a row.  If you're like me, you use the "Run Extension" option in the IDE a lot.  I'm constantly checking menu placements, and dialog look and feel, etc. while I'm developing the extension. Sometimes you run into issues where it just doesn't seem like the new changes are taking effect and you want to clean up the old extension files and start with a fresh environment.

NOTE:  These steps are for when you are doing a lot of start and stop testing.  You should not need to do this all of the time. Nor should you have to leave the caching setting, mentioned below, in place for normal development.

While JDeveloper does not officially support the uninstall of extensions (you can setup your extension to be disabled), there are ways to delete the extension while doing development so you aren't running into potential caching issues or just running into older versions of the jar files.

Cleaning things up

If you are doing everything in one jar file, it's really simple to clean things up and make sure you are not running into an older version of your extension. If your extensions is more complex, you will need to know what artifacts your extension is putting in what places, in order to clean them up.

One of the fastest ways to see what is being deployed, is to click on the "Deploy to Target Platform" in the context menu for your project.

This will open a Deployment Log window and you can see everything that is being deployed and to which locations.

Working with 11gR1

Once you know the location and name of the artifacts, close JDeveloper and open your favorite file manager to delete those files and/or directories.  After the files have been deleted, start JDeveloper back up.

Working with 11gR2

If you are working with the latest version of 11gR2, you will need to do the step above as well as a couple more steps to make sure you are not running into some potential caching issues.

First, when you add an extension via the Check for Updates feature in JDeveloper, information about that extension is added to an info file. This file is located at: <mw_home>/jdeveloper/configuration/cfu_bundles.info.  You will need to open this file in a text editor and remove the lines that pertain to your extension.  Be very careful that you don't remove lines that may be related to someone else's extension or an extension that you still want loaded. 

Second, when you right-click on the project and select "Run Extension" the IDE uses the default Run configuration for the project to startup the new IDE instance. To avoid potential caching issues when you are testing your extension, you will want to add a program argument to the default run configuration.

Double-click on the project name in the navigator and it will open the Project Properties dialog.  Select the Run/Debug/Profile option at the bottom left of the dialog


The Default run configuration should be selected, and you can just click on Edit to open it.


Look for the Program Arguments field and enter " -clean " in the field. With this argument you will have all of the caching cleared each time you use the Run Extension feature.  It does not remove any files or data.  It just cleans up the cache so that you are loading new versions of the extension libraries each time the command is run.

This is not something that you want to add to the actual IDE startup command, or have in place all of the time as it can remove some of the performance benefits that are new in 11gR2.

Conclusion

These couple of steps can save a lot of frustration at times.  I hope it helps others while doing the testing of your extensions.  I did mention above that you can setup your extensions to allow the end-user to disable them at runtime.  If you are interested in how to do that, please let a comment and if enough people are interested, I'll put up a separate post on how to do that in both R1 and R2.

As usual, comments are always welcome and encouraged!


Wednesday Aug 31, 2011

Running an audit from the command line with ojAudit

NOTE (UPDATE 9/30/2011):  This post currently does not work with 11gR2 (11.1.2.0.0) because of a bug.  The bug has been fixed in 11gR2 Update 1 (11.1.2.1.0). Please make sure you are running the latest release of R2.


 There is often a need to run an audit profile against a specific application, project, or even a file, and do it all from a script that may be part of a larger task.

JDeveloper provides a tool just for this task.  It's called ojAudit.

By default, you'll find this tool in the <oracle_home>/jdeveloper/jdev/bin directory.

If you run the tool without any arguments, you will get a really good usage guide, complete with examples.

The one thing that is needed by all of the examples, is a profile.  Let's look at how to create an audit profile so you can use it from the command line.

If you run JDeveloper and look under Tools >> Preferences >> Audit >> Profiles you will see a list of the profiles defined by default.

If you want to create your own profile, that is a subset of the existing rules, you can check and uncheck the various rules until you only have the ones that you want to run in your profile.  You will notice that the Profile name at the top of the dialog says that the currently selected profile has been (Modified).


Click on the Save As button and enter a new name for your profile.  You now have your own audit profile created and it can be used from the command line.  You don't need to know the location of the actual profile file, but by default, these audit profile files are saved at:

<UserDirectory>\Application Data\JDeveloper\system11.1.1.5.37.60.13\o.jdeveloper\audit\profiles

In the example above, you see that I am using version 11.1.1.5.37.60.13 of JDev.  In other words, 11gR1 PS4. Your systemXXXX will vary depending on what version of JDev you have installed. The rest of the path should be the same.

If you still can't locate the file, do a search on the name.  If you entered spaces in the profile name when you did the Save As in the dialog, the spaces will be replaced with " - ".  In the example that I used above, I named my profile to "My Audit Profile".  The resulting file is "my-audit-profile.xml". 

Once you have your profile created, you can use it from the command line like this:

ojaudit -profile 'My Audit Profile' -workspace <path-to-workspace(jws)-file>

If you forget exactly how you spelled your profile name, or just can't remember it because you created it a while ago, you can run:

ojaudit -profilehelp

and it will list all of the available profiles that can be used.

You can audit an entire workspace, a project, or a specific file.  If you point to a specific file, you will need to set  -classpath and -sourcepath for the files that you want to audit.

The report will output to stdout by default, so unless you are ok reading a bunch of xml from the command window, I would also add: -output report.xml

The final syntax would look something like:

ojaudit -profile 'My Audit Profile' -workspace <path-to-workspace(jws)-file> -output report.xml


Thursday Aug 25, 2011

Adding Exteneral Libraries to an Extension in 11gR2

I mentioned this recently in a comment response, but it has come up enough times now, that it deserves it's own topic.


MANIFEST.MF

If this is a new project in 11gR2, you should already see a MANIFEST.MF file in your project in the same location as the extension.xml.

If you don't see it, add the file in the META-INF folder along with the extension.xml file.
Add the default 3 lines to the file of:
Manifest-Version: 1.0
Bundle-ClassPath: .
<blank line>

Adding an External Library

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

You can verify that your external library is being added to the bundle by right-clicking on the project in the navigator panel, and selecting "Deploy To Target Platform".  In the Deployment tab of the Log window, click on the link to the deployed package and open the manifest.mf file to make sure everything is listed as you want it to.


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.

Go to project properties and click on the Deployment section. Select the "Extension" deployment profile and click on Edit.


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.

Tuesday Aug 16, 2011

Don't fear the Audit -- Part 2

In Part One of this topic, I covered the basics of creating an extension that will implement the audit framework and find a specific value for the FetchSize property of a ViewObject.  Once we found the value, we sent a Warning to the Editor if the value was greater then 100.

In this part, I'll cover how to create a Transform, or fix, that the end user can select to reset the value to the recommended value of 100, automatically.

An updated .zip of the sample project, with the transform code added, can be downloaded from here.

Just as with Part One, we will work with two separate areas of code.

The declarative entries in extension.xml and the code itself in the Transform class and the Transaction class.

Extension.xml

Previously I setup the <audit-hook> element in the extension.xml file, and I added a <rule-definition> to define what I wanted to report, when I found it. 

Similarly, I will add a <transform-definition> element to the audit-hook to define what the transform will be called, and where the transform class is located.


As you can see, the <transform-definition has one parameter of "id".  This must be a unique value.  As with the <rule-definition> I've set the label and description for this element in the resource file, instead of directly in the extension.xml.


Inside of the transform-definition is the <transform-class>.  I've added the entry that points to the class that I will be using to extend Transform.

Once you have the transform defined, you have to bind the rule to the transform, so that the IDE know which transform to display in the Editor.


Inside of the <rule-definition>, I've added a <transform-binding> element and the <transform> element which points to the ID of the transform definition that we set above.

That's it for the extension.xml.  Let's take a look at the Transform and Transaction classes now.

Transform class

The transform class must be a subclass of oracle.jdeveloper.audit.transform.Transform .

I'm going to be transforming an xml document so I'll make an explicit superclass constructor invocation of XmlTransformAdapter (for Java I would use JavaTransformAdapter).

To make sure all of this is done in a transaction, that can be undone by the end user, I've created the class FixFetchSize and called teh run() method to make everything happen.

Transaction class

The transaction class is a subclass of oracle.bali.xml.model.task.FixedNameTransactionTask.

I've overwritten the performTask() method to do the actual value replacement.

The Final Look

Once you have everything completed, if you run the extension from within the IDE (remember for 11gR2 you have to: Build, Deploy to Target Platform, then Run Extension)  you should find the audit available in the Tools >> Preferences >> Audits >> Profiles and if you run the audit against something like the Storefront demo, you will see something like this


Conclusion

Setting up the extension.xml to point at and use a transform is pretty simple. Getting the proper values from the file and making the modifications is where the real work is at.  In this particular example it took a lot more work to understand how to work with the XML document model and what to look for and replace, then it did to add the few lines in the extension.xml file. Hopefully this example will provide enough information to get you pointed in the right direction.

If you are going to be working with a Java file instead of XML, please take a look at the existing Extension SDK sample project called AuditRefactor for an example on how to work with java files.  It shows how to implement a transform by using the RefactoringManager, which can be very useful.

As with all my posts, if you have any comments, experiences, or questions, please add them to the post so everyone can learn from each other.


Monday Aug 15, 2011

Don't fear the Audit -- Part 1

Have you ever looked at the JDeveloper IDE, while you're writing code, and seen the warnings or errors that come up in the left and right gutters? Have you thought, "wouldn't it be great if the editor caught XYZ in my code?"

Well, you can write your own Audit extension to have the IDE look for just about anything.

The Audit Framework that comes with JDeveloper is very powerful, and really not that hard to extend.  It can help with maintaining company standards, or enforcing efficiency and protocol standards that may be set by your team.

You can even go as far as to write transforms (fixes) that will make the changes to the code for you when it finds something that you pre-defined.

For this topic, I'm going to use a project that I wrote specifically for this example.  You can download the entire project as a .zip file and place it into your work directory if you like.  I'm using JDeveloper 11gR2 for this example project. If you don't have this latest release, you can still follow along and I will try to point out the differences between the R1 syntax and the newer R2 syntax.

UPDATE (02/17/2012): There has been a nice write up about this topic, specifically done for 11gR1 over on Arvinder Singh's blog If you are using 11gR1 (11.1.1.x) then I would head over there as well.

In Part One of this topic, I'll cover the writing of the analyzer, to find the suspect code and send a report to the IDE.  In Part Two, I'll cover how to write a transform to automate the modification of what you report in the analyzer.

For most audits setting up the analyzer and having it report something to the IDE is all you need to do.

This is broken down into two parts.

  • Declarative entries in the extension.xml file
  • Analyzer class

The Extension.xml 

Let's start in the extension.xml file and work from there.

As you can see, we are going to add an <audit-hook> element to the file.  If you are using JDev 11gR1, this will go into the <hooks> section, if you are using 11gR2, this goes into the <triggers> section. Otherwise, the syntax is the same.

Let's take a closer look at each of the elements in the example above.

The <audit-hook> ID parameter must be a unique id.

The <category-definition> is what tells the IDE where to display the rules when you look at the Tools >> Preferences >> Audits >> Profiles dialog.
There is a label, description, and message parameter for the category-definition element. I've set these in a Resource file instead of putting them directly in the extension.xml file.  I've done the same thing for the <rule-definition> element. Here is what that resource file looks like.


The <rule-definition> element is really where everything is setup.


The ID parameter has to be a unique string.

The category is set to the category that you defined above, or an existing category that you know the ID of.

Enabled is set to true or false.  This is very important.  If this is set to true, the IDE will run your audit as soon as the file is loaded in the editor.  It's best to set this to False until you know what impact your audit is going to have on performance of the editor.  If you do something really time intensive in the analyzer class, it could bring the editor to a crawl.

The severity element can be set to one of four options.

  • Error
  • Warning
  • Incomplete
  • Advisory
  • Assist

All of these have a different way of displaying in the IDE when they are encountered by the audit framework. The Error value will stop the compiler from completing until the issue is resolved.

The parameter element is optional.  This is what you will use to pass any values back from the audit.  You may want to pass a value back to be used in the message that is displayed in the editor when you mouse over the issue.  Take a look at the Resource file example that I included above, and you will see how I am using the "currentsize" parameter in my message.

Multiple Rules can be setup in an audit-hook element.  However only one analyzer class can be referenced per audit-hook so it's best to group rules into common analyzers.

The <analyzer-definition> element is set to point to the analyzer class that the rules will be implemented in.

The Analyzer Class

The analyzer class is where all of the real work is done.

An analyzer class must be a subclass of oracle.jdeveloper.audit.analyzer.Analyzer.


Before Audit begins each traversal, it creates new Analyzers instances, creates and configures new Rule instances, and injects the rules into the analyzers. The @ExtensionResource annotation on the INVALID_FETCH_SIZE field instructs Audit to inject the instance of the Invalid Fetch Size rule into the field. The analyzer will need the instance stored in that field to report an issue.

In this class you can implement validation code for the workspace (application), project, document, and element.  In the traversal, the audit framework will visit the objects in the model as follows:

  • Enter Root
  • Enter Workspace
  • Enter Document
  • Enter Element
  • Exit Element
  • Exit Document
  • Exit Workspace
  • Exit Root

For this example, I don't have any validating to do in the workspace or project methods, so I'll skip down the document method and start there.


In this method I check to see if the first node in the document is "ViewObject" and if the file name ends with VO.xml. If this criteria is not met, then we set the setEnabled() method to false, disabling the audit for this traversal.

When the setEnabled() method is set to False, it stops the traversal from going any deeper into the process.  It will immediately start the return trip in the traversal and call the appropriate Exit methods.

If this method passes, then it continues down into the Enter method for the Element. You do not need to do a setEnabled(true).


Here we check to make sure that the FetchSize element exists and if so, and if it does, we check to see if a value has been set. We do our test to see if the value is greater then 100 and if so, we return the report, adding our parameter that we set in the extension.xml.

If we had created multiple rules in the extension.xml file, and they all defined some kind of audit on a ViewObject, we could do multiple validations here in this method. 

You would need to add an additional @ExtensionRegistry and "private Rule" definition for each rule at the top of the class, and then set the report variable to send out the report to the different rules as needed.

To run your audit, you can click on whichever object you want to run the audit against (Workspace, Project, file) and then click on the Build menu in the main menu bar. At the very bottom of the menu list, you will see "Audit <object>".


You'll notice in the example above, I have the Project selected in the Navigator window, and in the Build menu, it is showing "Audit Audit-Sample.jpr" which will run my audit against all of the files in the project.

To make sure your audit rule will be run, look at the Tools >> Preferences >> Audits >> Profiles dialog and make sure your rule is checked.

Getting Audit Extensions to load in 11gR2

If you are working with 11gR2, you will find that the audit extension will not fully load when you run it.  Looking at Help >> About >> Extensions you will see that your extension has "Triggers loaded" but it never gets to "Fully loaded". This is a result of the lazy loading feature introduced with 11gR2.  To get the extension to load when it's first initialized, we add the following element to the <audit-hook> element.

        <trigger>
          <technology>ADFbc</technology>
        </trigger>

The value for <technology> is a technologyKey and will cause the extension to be loaded when a project is initialized that uses this technology.  For this example, I've set it to ADFbc since I am doing an audit against an ADF application with the ADFbc feature enabled.

Conclusion...

In this post I covered the basics of creating an audit extension that audits and XML file. In Part Two I add a transform (fix) to this same project.

A very special Thank You! to Louis Tribble (Audit Framework master) and Jun Shozaki who spent countless hours traveling the internal roads of the Audit framework, and thankfully documenting them. Without these two developers, this topic would not be written.

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

Wednesday May 11, 2011

Letting the Usage Reporting feature show you the way

Some times when you're looking to start an extension project, you're just not quite sure where to start to accomplish the task that you have in mind.  Maybe it's something that is already possible in JDeveloper, but you just want to modify it in some way, or do things a little bit differently then the current functionality.

One way to look at what is going on behind the scenes, is to enable the Usage Reporting feature in JDeveloper and look at the usage log that is generated after you do a certain process in the JDeveloper UI.

prefereces setting for Usage Reporting feature

This report will not show you the code that you have to write, but it will show you the extension classes being called when you perform certain steps in the IDE, and that could be enough to give you something to look up in the javadocs and get going in the right direction 

Of course this will only happen if you have opt-in to the usage-reporting feature in the first place. Which you can do on the Preferences panel as shown above.

What the Usage Reporting feature does, is create an xml file after each IDE session. It records some of the API usages during that session. A session is defined as the time in the IDE from startup to close.

By default the usage log is saved to the location shown below on a windows machine. This install was done with the Local Users option selected during the installation. The location could vary depending on how you did your installation.

C:\Documents and Settings\<username>\Application Data\JDeveloper\system11.1.1.5.37.60.13\o.ide.usages-tracking

The systemXXX number will vary depending on which version of JDeveloper you have installed.  The one above, shows the version number for JDeveloper 11.1.1.5.0 (the newest version as of this post)

The Trick...

There is one trick to being able to actually look at the usage log, before it's sent off to Oracle. 
To stop the file from just being sent and erased as soon as you close JDeveloper,  you will need to set some bogus proxy info in the Tools --> Preferences --> Web Browser and Proxy panel.

proxy settings in preferences

The file will stay in that location until JDeveloper can connect again. If you don't want the file to be sent, just go ahead and delete it after you are done, or move it to another location.

The data that is gathered is used internally by the JDeveloper product management and engineering teams to help make more educated decisions on feature updates and enhancements, as well as adding new features down the road.

Here is the contents of an actual report that was created as the result of opening an extension.xml file and then opening a .java file.


<?xml version = '1.0' encoding = 'UTF-8'?>
<usages xmlns="http://xmlns.oracle.com/jdeveloper/110000/usages-tracking-data">
   <hash n="system-info">
      <value n="build-label" v="JDEVADF_11.1.1.5.0_GENERIC_110409.0025.6013"/>
      <value n="dev-build" v="false"/>
      <value n="guid" v="07dd49ee-012e-1000-8001-0a9a27d99b84"/>
      <value n="jdk-version" v="1.6.0_24"/>
      <value n="operating-system" v="Windows XP"/>
      <value n="product-edition" v="oracle.studio, oracle.j2ee, oracle.jdeveloper"/>
      <value n="product-name" v="Oracle JDeveloper 11g Release 1"/>
      <value n="product-version" v="11.1.1.5.37.60.13"/>
      <value n="session-end-time" v="1305043200531"/>
      <value n="session-id" v="1305043105550"/>
      <value n="session-start-time" v="1305043105550"/>
      <value n="user-role" v="<none>"/>
    </hash>
    <hash n="usage-data">
      <list n="activities">
        <hash>
           <value n="extension-product-id" v="oracle.jdevimpl.extensiondt.editor.ExtensionManifestEditor"/>
           <value n="property-id" v="oracle.jdeveloper.extensiondt.model.ExtensionManifestNode"/>
           <value n="time-stamp" v="1305043182769"/>
           <value n="usage-type" v="OPEN_EDITOR"/>
        </hash>
       <hash>
         <value n="extension-product-id" v="oracle.jdevimpl.extensiondt.editor.ExtensionManifestEditor"/>
         <value n="property-id" v="oracle.jdeveloper.extensiondt.model.ExtensionManifestNode"/>
         <value n="time-stamp" v="1305043182832"/>
         <value n="usage-type" v="ACTIVATE_EDITOR"/>
       </hash>
       <hash>
         <value n="extension-product-id" v="oracle.ide.ceditor.CodeEditor"/>
         <value n="property-id" v="oracle.jdeveloper.model.JavaSourceNode"/>
         <value n="time-stamp" v="1305043190096"/>
         <value n="usage-type" v="OPEN_EDITOR"/>
       </hash>
       <hash>
         <value n="extension-product-id" v="oracle.ide.ceditor.CodeEditor"/>
         <value n="property-id" v="oracle.jdeveloper.model.JavaSourceNode"/>
         <value n="time-stamp" v="1305043190767"/>
         <value n="usage-type" v="ACTIVATE_EDITOR"/>
       </hash>
     </list>
   </hash>
</usages>

As usual, please feel free to post any questions or personal experiences in the comments.

Monday Sep 06, 2010

Declarative Menus in JDeveloper Extensions – Part Three

Part Three: Creating Gallery menus (File / New) using a Wizard

If you came to this post directly, you may want to take a look at the previous posts first.
Part One: Introduction and Creating an Action
Part Two: Creating Context Menus

Using the JDeveloper SDK Sample project, "Create Dialog" we can take a look at how the extension.xml is setup for using a Gallery item.

image

extension.xml

The nice thing about setting up a Gallery item is that it can be done with a simple Wizard.  From the File menu, select New and look for the "Gallery Item (Wizard)" in the Extension Developer folder under Client Tier.

image

If you don't see the Client Tier category when the dialog first opens, make sure you are on the "All Technologies" tag and not the "Current Project Technologies" tag.

Double click on the Gallery Item option and you will see a dialog like the one below.

image

Enter the name of your Gallery item.  You can select the Category and Folder from the pulldown list, or type in your own. You can also select the icon that will be displayed with your menu item at this time.

NOTE:  Take a careful look at the "Wizard class" name that is being created for you.  Specifically make sure that the package name in front of the actual class name is what you want it to be.

The checkbox for adding this to the Tools Menu is something that I haven't used that much. It adds the menu item using a MenuSpec object in the code.  I'll cover how to work with the main MenuBar and ToolBar menus declaratively in Part Four of this post.

Click OK once you have all of your data entered and the wizard will add the basic lines to the extension.xml file and create a new class file based on the wizard class name that you set in the dialog.

image

If we look at the java class created by the wizard, you'll see two methods that manage the execution of the menu item.  

The "isAvailable" method is where you add any code that will tell the IDE when to actually show your menu item.  In the example above, you can see that this menu item is only going to be shown when there is a valid Project in the application.

The "invoke" method is where you will define the UI for your wizard or perform the action for the menu item.  In the example above, a call is made to the runDialog() method in another class that does all of the UI work. 

If we take a look at what the wizard added to the extension.xml file, we'll see that  the basic elements are added in for us.  "name" (which is pulled from the generated class), "category", and "folder".

image

The result of this is what you see below.

image

Notice however, that this only shows up in the "All Technologies" tab.  If we look at the "Current Project Technologies" tab, our menu item isn't there.

image

The Current Project Technologies tab is a filtered list of items. It only shows items that are related to the Technology Scopes that you are using in the current project.

If you know that your extension is working with projects that have a specific Technology Scope, Java for instance, you can set the menu item to show up in the Current Project Technologies tab when that Tech Scope is present by using the "technologyKey" element, right after the "folder" element, in the extension.xml file.  If your extension is working with any project, no matter what the tech scope may be, you can still set the technologykey to "General" and it will show up for any project.

<technologyKey>General</technologyKey>

image

To determine what the correct value is for the different technology scopes, just click on the "selected technologies" link at the top of the dialog and you'll see a complete list.

As usual, please post up any questions or personal experiences in the comments.

Previous parts in this topic:

Part One: Introduction and Creating an Action
Part Two: Creating Context Menus

Next Steps:

-- Part Four: Creating  Toolbar and Menubar menus

Thursday Aug 26, 2010

Declarative Menus in JDeveloper Extensions – Part Two

Part Two: Creating Context Menus

If you came to this post directly, it would be a good idea to take a look at the previous posts first.
Part One: Introduction and Creating an Action

You can create a context menu in the Navigator panel, the Explorer or Structure Panel, and the Editor window.

To create these menu items you want to first create a listener class that you can then tell the IDE to interact with.

Using the JDeveloper SDK Sample project, “First Sample” we can take a look at how the listener is defined in the extension.xml and in the Listener Class itself.

image

extension.xml

image

Listener class

Notice that the extension.xml file makes the reference to the Listener class, and that class goes back to the Action that we discussed in the first part of this topic. The Action is where the class is called to actually do the work when the menu item is clicked.  You can setup a Controller class to manage the command ID’s as Constants if you like.  I’ve chosen to do a direct call to the Action ID in the sample above.  Notice that the controller method is also there, just commented out.

It’s the site “idref” that determines where the context menu item will show up in the UI (Editor, Navigator, Explorer).  Of course you can have multiple Listener classes. One for each type of context menu that you want to setup.

While there isn’t a wizard for setting up Context Menus, it can still be done pretty quickly by using a bit of cut and paste from this one SDK example project.

There are multiple projects in the SDK Samples that use context menus.  To see more examples, take a look at the following projects:

ClassSpy
CodeInteraction
Overlay

As usual, please post up any questions or personal experiences in the comments.

Previous parts in this topic:

Part One: Introduction and Creating an Action

Next Steps:

-- Part Three: Creating Gallery menus  (File / New) using a Wizard

-- Part Four: Creating  Toolbar and Menubar menus

Wednesday Aug 25, 2010

Declarative Menus in JDeveloper Extensions – Part One

When creating an extension for JDeveloper, the most common way of connecting that extension to the IDE is through the menu structure.

Whether it's via a context menu, or adding a menu to the existing menu bar at the top of the IDE, it can all be done in two different ways.  In code, or declaratively in the extension.xml file

In this post, I'm going to talk about how to work with the declarative method for menu creation, as I believe it is the easiest and most flexible way to connect to the IDE.

All of the IDE commands used here, are available when working with an Extension Project type.

I will break this post into multiple sections since it's a bit of a long topic

Part One: Introduction and Creating an Action

Part Two: Creating Context menus

Part Three: Creating Gallery menus  (File / New) using a Wizard

Part Four: Creating  Toolbar and Menubar menus

The SDK example application "First Sample" does a really good job of showing how to add a menu to the following areas of the IDE:

Context Menu for:

Navigator
Editor
Explorer (Structure pane)

image

New Gallery

image

Menubar

image

Toolbar

image

The above examples show the proper syntax for working with all of the different kinds of menus.  However, they don't give you the information about how to find the ID for the menu areas that you want to add to, or how to nest menus.  We'll go into more detail about how to do these things as well as take a general look at how everything is tied together.

Getting Started (creating an action)

The first thing you need to do when working with menus, is to create the action section that will define what the menu item will do.  All of the menu items will reference this action to get the actual work done.  This is made very simple in JDev 11g by using the "File -> New" Wizard to add an Action to the existing extension project.

Right-Click on your extension project name in the Navigator pane and select New.  In the resulting Wizard, make sure the "All Technologies" tab is selected and then click on the Extension Development folder under the Client Tier  category.

image

Double click on the Action item and fill out the dialog with the information about your new Action.

image

You can select an Icon for your menu item from the OracleIcons group here, or you can add an icon to the project at a later time and then reference it in the extension.xml file later.

Once you have created your action, it will look like this in the extension.xml file

image



Next Steps: 

-- Part Two: Creating Context menus

-- Part Three: Creating Gallery menus  (File / New) using a Wizard

-- Part Four: Creating  Toolbar and Menubar menus

Monday Jul 26, 2010

What's New in JDeveloper 11gR2 Extension Development

With the release of JDeveloper 11gR2, the entire Extension Framework has been reworked so that extensions are now implemented as OSGi modules. Extensions written for previous versions of JDeveloper will not work with this release until you do some modifications to your code.

What does this mean to extension developers?

Lazy Loading

The biggest impact is when and how an extension is loaded.  Jdeveloper use to load all extensions at the same time when JDeveloper was first started.  We now take advantage of something called Lazy Loading.  Extensions are only loaded when the developer needs them.  This allows JDeveloper to have a much faster startup time, and also a lower memory footprint while running since extensions that you don't need, are not loaded.

Trigger Hooks

With this release, there is the introduction of Trigger-Hooks in the extension.xml file.  This is separate from the older Hooks element.  Because an extension isn't loaded automatically by calling the Addin.initialize() method any longer, you need to add an action or event to the trigger-hooks section so the IDE knows when to load your extension.
You can take a look at the trigger-hooks wiki to see the existing trigger-hooks available in this release.

Separate Classloaders

With the use of OSGi, comes the use of a separate classloader for each extension.  You may have to change how your extension sets it's dependencies. The classpath element in extension.xml is no longer used. You set the dependencies in the Manfest.MF files instead.

Run and Debug from the IDE

There is an extra step now for running or debugging your extension from within the IDE.  Before you click on the Run Extension or Debug Extension options, you must click on "Deploy to Target Platform" first.  This rebuilds the Manifest.MF files with any changes to your project.  This will become a little smoother in a future release, but for now, you just have to do this one extra step.

JDeveloper Extension Development Guide

With such a significant change to the framework, we had to update the documentation to go with it of course.  A completely new Extension Developer Guide has been written for this release.  It's a great place to start.

What's next?

Those are the major changes for the Extension Framework in this release. They are quite significant.  I will be posting another entry shortly where I will walk through the steps of taking an existing extension project, and migrating it to work with the new OSGi enabled framework.  Stay tuned for more.

As always, please feel free to post any questions or personal experiences in the comments. I'm sure everyone's experiences with migrating existing extensions will be of benefit to all of us.




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