Monday May 21, 2012

Setting up a Fusion Applications Development Environment

With the release of Oracle Fusion Applications, there has also been the release of the Fusion Application extensions for JDeveloper. Installing and configuring these extensions is referred to as the FA Dev Environment.

One very important thing to note, is that creating extensions for Oracle Fusion Applications, is NOT the same as writing extensions for JDeveloper.  You are writing and extending the Application functionality, using JDeveloper as the dev environment.

With that said, I wanted to still cover this topic in this blog, because it involves the installation and configuration of JDeveloper Extensions that help with the customization of those Fusion Applications.

Hope that makes sense.  :-)

Downloading the proper version of JDeveloper and the FA Extensions

The version of JDeveloper and the FA Extensions is directly related to what version of Oracle Fusion Applications you have installed on the servers. You get the different releases, from the eDelivery website, under product pack Oracle Fusion Applications .
DO NOT download a version of JDeveloper off of the OTN website and use it to setup the Fusion Applications Dev environment.

No matter which version you download, you will need two different downloads.

  • JDeveloper installer (Oracle JDeveloper 11g and Oracle Application Development Framework 11g)
  • Fusion Application Extensions Bundle (Oracle Fusion Applications Companion 11g)
Part #'s for FA V1 RUP1 on http://edelivery.oracle.com
Part#: V28727-01 :: Oracle Fusion Applications Companion 11g (11.1.1.5.3)    
Part#: V28726-01 :: Oracle JDeveloper 11g and Oracle Application Development Framework 11g (11.1.1.5.3) (Part 1 of 3)    
Part#: V28726-01 :: Oracle JDeveloper 11g and Oracle Application Development Framework 11g (11.1.1.5.3) (Part 2 of 3)    
Part#: V28726-01 :: Oracle JDeveloper 11g and Oracle Application Development Framework 11g (11.1.1.5.3) (Part 3 of 3)    

Part #'s for FA V1 RUP2 on http://edelivery.oracle.com
Part#: V31524-01 :: Oracle Fusion Applications Companion 11g (11.1.1.6.1)    
Part#: V31523-01 :: Oracle JDeveloper 11g and Oracle Application Development Framework 11g (11.1.1.6.1) (Part 1 of 3)    
Part#: V31523-01 :: Oracle JDeveloper 11g and Oracle Application Development Framework 11g (11.1.1.6.1) (Part 2 of 3)
Part#: V31523-01 :: Oracle JDeveloper 11g and Oracle Application Development Framework 11g (11.1.1.6.1) (Part 3 of 3)

Part #'s for FA V1 RUP3 on http://edelivery.oracle.com
Part#: V31981-01 :: Oracle Fusion Applications Companion 11g (11.1.1.6.2)    
Part#: V31980-01 :: Oracle JDeveloper 11g and Oracle Application Development Framework 11g (11.1.1.6.2) (Part 1 of 3)    
Part#: V31980-02 :: Oracle JDeveloper 11g and Oracle Application Development Framework 11g (11.1.1.6.2) (Part 2 of 3)
Part#: V31980-03 :: Oracle JDeveloper 11g and Oracle Application Development Framework 11g (11.1.1.6.2) (Part 3 of 3)

(Other releases that come out after this posting will be found in the same  http://edelivery.oracle.com location, with newer part numbers. The naming should remain the same)

TIP: If you are installing on Windows only, you can just download the companion archive and Part 3 of 3 for the JDeveloper IDE.  Part 1 is the .jar installer and Part 2 is the .bin installer for other operating systems.

Once you have the appropriate bits downloaded, and extracted, you can start the steps for getting everything installed and configured.

Installing JDeveloper and FA Dev Extensions 

This is a pretty normal step.  Just install JDeveloper as you would on any other machine. With one exception:

  1. Do not install JDeveloper into a path that contains spaces (the default is C:\Oracle\Middleware)

The entire process for setting the proper environment variables and setting up the Update Center for installing the FA Dev Extensions, is described in detail in the online documentation under the Setting Up Your Development Environment section.

A couple of things to watch for when setting up the environment listed in the docs.

  1. Do Not include the quotes " " around the values for USER_MEM_ARGS variable on Windows.  This is a typo in the docs.
  2. It is best to use the JDK that ships with JDeveloper on Windows.  You do not need to use a 64bit JDK. For other operating systems make sure you use something equal to or above jdk160_24
  3. When the docs tell you to change directories to $MW_HOME/jdeveloper/jdev/bin  and run JDeveloper, this is mainly for non-Windows OS's.  However if you do run on Windows from a command window it could allow you to see some of the error messages if there are any.  You can still run JDev from the Start Menu if you like.  

Configuring the Fusion Domain

Once you've installed the FA Dev Extensions, and restarted JDeveloper, you select either the "Oracle Fusion Applications Developer" or "Oracle Fusion Applications Administrator Customization" role at startup.

As you will see in step of 7 of the online documentation, you will now be prompted to configure the Weblogic Server.  This involves filling out the Fusion Domain Configuration wizard and letting it do it's thing.

A couple of things to watch for before and during the running of the domain config wizard

  1. Make sure you have Python 2.7.2 or higher installed in a path that does not contain spaces. 
  2. DO NOT use Python 3.x
  3. Take a look at your system PATH environment variable and remove any entries that have spaces in them
    1. The easiest way to do this on Windows is to open a command window and set the PATH variable to just contain "." and the path to your Python installation. (e.g. set PATH=.;c:\python272 )
    2. Then start JDeveloper from this command window
  4. When you run the Fusion Domain Configuration wizard, you will be given an option to test the connection to the application server on one of the pages.  If it fails during the tests, but you know FOR SURE that you have the login credentials correct, try entering the IP address of the host instead of the hostname in the connection URL.  We have seen some DNS issues cause errors during the test page.

Follow all of the tips above and you should get the domain configured and extended properly.

Troubleshooting

 There are always exceptions to the rule.  If you run into issues, try looking at these tips.

Error logs

There are two different types of log files that can help find an answer to whatever issue you are running into.  Server logs, and config logs

  • D:\jdevuserhome\system11.1.1.5.38.61.26\DefaultDomain\servers\DefaultServer\logs
  • D:\jdevuserhome\system11.1.1.5.38.61.26\o.apps.fadev.11.1.1

 Some common error messages

"...\Java\jre6\lib\ext\QTJava.zip was unexpected at this time."

 This error is usually caused by the QT entry in the CLASSPATH containing spaces.  You can get around this by removing the Quicktime/QT entry from the end of the CLASSPATH


"... wlst create default authenticator failed" 

or 

 "java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: The provider OIDAuthenticator already exists"

or

"OracleScriptingException: The MBean oracle.wsm:*,name=WSMDocumentManager,type=Repository was not found." 

 All of the above errors, or errors similar that mention *wsm* are usually caused by the owsm_mds schema not existing. If you look at the Dev Guide, in section 2.2.1.6, it explains that this schema is usually not available in production or test databases. The Fusion install doesn't create it in the starter database; it's expected to be in the IDM database. Go back and read this section of the Dev Guide to install and configure the owsm_mds schema.


The configuration script seems to just hang while running "FADevConfigure.py"

If you followed the tips and hints above, you shouldn't hit this issue.  However if you do, make sure you go back and check to see if you have quotes around any of your Windows environment variables, and if your PATH setting has spaces in it.  


When testing your application server connection you see something like:

Testing JSR-160 Runtime ... failed
Cannot establish connection.
Testing JSR-160 DomainRuntime ... skipped
Testing JSR-88 ... skipped
Testing JSR-88-LOCAL ... skipped
Testing JNDI ... skipped
Testing JSR-160 Edit ... skipped
Testing HTTP ... success
Testing Server MBeans Model ... skipped
Testing App Controller ... success

This is usually solved by setting the IP address of the application server in the connection URL instead of the hostname. 

Conclusion

 With the tips and hints listed above, along with the common error messages in the troubleshooting section, you should be able to get up and running pretty quickly.  If you run into other issues setting up the development environment, please don't hesitate to drop a comment below.  Please DO NOT ask me questions about how to do the customization of the FA applications themselves.  If you're trying to edit files, I'm not going to be the person to help you out with that.

Special Thanks to Oliver Steinmeier for a lot of the answers and troubleshooting of customer issues internally, so that we can compile these types of lists. 

Friday Nov 11, 2011

Attention Extension Developers: Your input wanted!

Your Input Wanted!

I've posted a lot of different topics throughout 2011, and would really like to provide info that is most important to you, the extension developer, as we head for 2012.

What are the most important areas that you want to learn more about?

Post your requests for examples and topics in the comments section. Let me know what you are struggling with, or something that you worked out, but it took way to long to figure out.  I'll take the list and do my best to provide samples over the coming months.

Please provide the version of JDeveloper that you want the topic to cover.

Remember:

11gR1 = 11.1.1.x (e.g. 11.1.1.5.0)

11gR2 = 11.1.2.x (e.g. 11.1.2.1.0)

Thanks in advance for your comments and suggestions.  Let's get the JDev Extension community going in 2012!

--jb

John "JB" Brock
Oracle Product Manager - JDev ESDK



Tuesday Nov 08, 2011

Updating an existing file via the SDK

In my last post I showed how to add a file to an existing project, and have it show up in the project navigator. In this post, I'll give a very basic example of how to edit that file and have those changes show up in the editor right away.

This code is appropriate for both 11gR1 and 11gR2

Working with a files content in Java is usually done via the FileIO and buffers. When working with the content of a file that is already open in a JDev editor window, you want to do things a little bit differently.  Instead of modifying the file directly, we can use a TextNode and the acquireTextBuffer() method to get the TextBuffer that we will then modify. This will allow the IDE to handle the saving of the file to the filesystem, as well as updating the editor window so you see the changes as soon as they are made.


Setup

I've created a really simple xml file that I will use for this example.


I'm using a modified version of the FirstSample extension SDK sample project.

I've setup a context menu item in the extension.xml file that will only show in the Editor window when the context has an XML file being edited. Notice the "rule" setting. This is where the restriction is set.


I've done all of the work in the Controller classes handleEvent method. Here is what the try / catch block looks like



How it works

In the try / catch block above, we first make sure that we are dealing with a TextNode from the context that is passed to us from the context menu.

We then get a buffer that contains the current editors text.  We dump the entire buffer contents into a String variable and make the modifications to the string.

Once all of the modifications are made, we convert the String variable into a char array so that it can be used with the EditProcessor class.

The EditProcessor class is the magic of all this.  Instead of trying to do the buffer locks and beginEdit and endEdit methods ourselves, we can simply use the methods available to us from the EditProcessor and all of the undo state and locks will be handled for us.  It will even set the file in the editor to a dirty state so it shows that it has been modified.

The arguments that we pass into the doReplaceAll() method are:

-- char[] of the content that we want to be placed into the node.
-- the node that we want to change
-- true or false to set this change as undoable
-- a String that will show up in the Undo menu item.  It will read as "Undo <string message>"
-- the origin object.

You can read more about the other methods in the EditProcessor class from the JavaDocs

Conclusion

Don't use the file.io classes to modify a file that is currently open in the IDE editor window.  Instead, use a TextNode and the TextBuffer associated with the current context to let the IDE do most of the work for you.  And remember to take advantage of the EditProcessor class instead of trying to do all of the undo and buffer locking yourself.


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.


Thursday Oct 13, 2011

Writing, Running, and Debugging Your First JDev Extension

It recently came to my attention, that while I've talked about it many times in the different posts on this blog, I've never written a post just about getting started with your first JDev extension.

Sorry about that!

So here I will finally correct that.  I'm going to quickly cover the basics of starting an extension project from scratch and then how to run it from the IDE, and how to debug it from the IDE.  I'll toss in NOTES when there is a difference between the R1 process and the R2 process.  Most of it is still the same between versions of the IDE

To keep this at the beginners level:  R1 refers to any version of the IDE that is 11.1.1.x  where R2 is referring to anything 11.1.2.x and higher.  You can read the post about migrating extensions from R1 to R2 to get some details about what is different in the newest release of the IDE.


Creating a new Extension Application and Project

There isn't a specific Extension Application selection when you go to the New Gallery and click on Applications. You will need to create a Generic (R1) or a Custom (R2) Application.


Double-Click on the application item to start the wizard.

Just enter the Application name and click on the Finish button at the bottom of the dialog.

The wizard will create a default project called "project1".  Right-click on the project name and select "Delete Project".
You should select the option to remove the project and all of it's contents so we don't have junk code laying around in your work folder.  We don't need this default project, as we will create our own extension project next.

Right-click in the empty space of the Application Navigator and select "New Project from the context menu.


Click on the Extension Development option under the Client Tier category, and then double-click on the "Extension Project" option.


Once the project creation wizard comes up, fill out the name of the Project with some thing that you like.

Give your project an identifier.  This is what will be used in your library path.

The rest will be filled in for you with the information that you gave in the two entries above.



After the project is created, your IDE screen should look similar to this


Running the Extension

Now that we have our project created we can start work doing all of the things that I've already written blog posts about.  For the sake of making this post only about Writing, Running, and Debugging, I'm going to just paste in some code and jump ahead to how to run the code from within the IDE.

After the project is saved and built(compiled) you can right-click on the project name in the Application Navigator and select "Run Extension".  This will start another instance of the IDE with your extension loaded so you can see how it works.

NOTE: In 11gR2 you must click on the "Deploy to Target Platform" menu item before you Run or Debug the project. This is required to setup the MANIFEST.MF file with any changes that you may have made to your code, and then package everything up properly.  This is not required for the 11gR1 version of the IDE.

Any error messages or warnings that occur during the running of the extension, will show up in the log window of the Parent IDE.  This includes any System.out.* commands that you may have put into your code.


Debugging the Extension

You can set breakpoints in the code just like you would for any other type of code. To debug your extension, save the project, then right-click on the project name in the Navigator and select the "Debug Extension" option. The new instance of the IDE will start up, and you can perform the functions of your extension in that test instance.


NOTE:  The same thing applies for Debugging as Running in 11gR2.  You must click on the "Deploy to Target Platform" option before you click on the Debug menu item each time.

When the debugger hits a breakpoint in the code, the Parent instance of the IDE will show all of the debug info.




Conclusion

As you can see, it's pretty simple to run and debug you extension directly from the IDE.  There isn't a need to save off the extension .jar file to the extension folder and restart the IDE like a lot of people have been doing.  I hope this helps speed up development for people, and makes extension development just a little bit smoother for everyone.

As always, please post comments or questions so all developers can learn from each other.


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 Jun 15, 2011

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.

Monday Jun 13, 2011

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!


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.

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