Creating an Extension to JDeveloper

Purpose

Use this tutorial to build a simple wizard that can be invoked to create a configurable "Hello World" method. When completed and installed, this wizard can be invoked from either the Tools menu or the New Gallery to create a simple Java application in JDeveloper.

Topics


 Overview
 Prerequisites
 Step 1 - Creating the Hello X Wizard Project
 Step 2 - Creating the Hello X Wizard
 Step 3 - Creating the Archive Description File
 Step 4 - Deploying the Hello X Wizard
 Step 5 - Debugging Hello X 
 Summary

Time to complete

This tutorial should take about an hour to complete.
 

Viewing Screenshots

 Move your mouse over this icon to show all screenshots. You can also move your mouse over each individual icon to see only the screenshot associated with it.


Overview

An extension is a package of files, usually an application or set of wizards in a ZIP or JAR file, that can be added to JDeveloper. Many standard JDeveloper components (features) are installed as extensions. This lesson shows how to create, deploy, and utilize a wizard extension.

Scenario

You have been given the task of creating a wizard that generates Java Code and places the class file inside a JDeveloper project. You create a wizard that is deployable to other instances of JDeveloper. 

Prerequisites

Before starting this tutorial, you should have completed the following:

1.
Install Oracle JDeveloper10g.
 

0&&parent.frames.length) { d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);} if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<(a.length-2);i+=3) if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];} } //-->

Step 1 - Creating the Hello X Wizard Project

This step explains how to create a workspace and project to contain the extension you wish to add to JDeveloper, and add the libraries you need.
 

1. In the Application Navigator, right-click Applications and select New Application Workspace.

Move your mouse over this icon to see the image

 

2. Fill in the Create New Application Workspace dialog using the values listed:

For Application Name, enter HelloX .
For Directory Name, enter <your_hard_drive>:\hello_x .
This change from the default is to make clear the difference between the HelloX method, the directory where project files are stored outside of JDeveloper ( hello_x), and the package name in this tutorial ( hellox).
For Application Package Prefix, enter oracle.jdev.hellox . The source code you will copy has been created for a package of this name.
For Application Template, select No Template [All Technologies] , because you do not need JDeveloper to create any files or structures for you.

Move your mouse over this icon to see the image

 

3. Click OK to add the workspace. JDeveloper creates a project named Project in the HelloX workspace.

Move your mouse over this icon to see the image

 

4. In the HelloX workspace, right-click the Project node and select Project Properties to open the Project Properties dialog.

Move your mouse over this icon to see the image

 

5. In the Project Properties dialog, select Profiles | Development | Libraries to display the list of libraries which can be made available to the project in the Available column, and those which a Java file in the project can successfully access in the Selected column. Move these libraries to the Selected column if they are not already there: JDeveloper Runtime, JDeveloper Extension SDK . The Java file that you create in the next step imports classes from these libraries.

Move your mouse over this icon to see the image

Click OK to close the Project Properties dialog.

 

6. Select the workspace node, then choose File | Save All to save your work.

0&&parent.frames.length) { d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);} if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<(a.length-2);i+=3) if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];} } //-->

Step 2 - Creating the Hello X Wizard

The HelloX class contains all the methods used to create the Hello X wizard and to control what the wizard does. You create the class and store the physical files outside of the JDeveloper home directory to make it easier to reuse the method.
1. Right-click the Project node in the HelloX workspace and select New to display the New dialog.
 

Move your mouse over this icon to see the image

 

2. In the New dialog, select General | File to display the Create File dialog. Enter HelloX.java for the filename. Enter <your_hard_drive>:\hello_x\Project\src\oracle\jdev\hellox as the directory name.
Notice the path after \src matches the Application Package Prefix you entered when you created the workspace.

Move your mouse over this icon to see the image
 

Click OK to create the file.

 

3. Copy all of the following code and paste it into the HelloX.java file:
 

// Copyright (c) 2001, 2003, Oracle. All rights reserved.

package oracle.jdev.hellox;

import oracle.ide.WizardManager;
 

import java.net.URL;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;
import javax.swing.Icon;
import java.lang.reflect.Modifier;

import oracle.ide.Ide;
import oracle.ide.cmd.buffer.Edit;
import oracle.ide.editor.Editor;
import oracle.ide.editor.EditorUtil;
import oracle.ide.editor.EditorManager;
import oracle.ide.util.GraphicsUtils;
import oracle.ide.util.MenuSpec;
import oracle.ide.addin.Context;
import oracle.ide.addin.Wizard;
import oracle.ide.addin.Addin;
import oracle.ide.model.Project;
import oracle.ide.model.NodeFactory;
import oracle.ide.net.URLFactory;
import oracle.ide.net.URLPath;
import oracle.jdeveloper.model.JProject;
import oracle.jdeveloper.model.JavaSourceNode;
import oracle.jdeveloper.jot.*;

/**
* This sample demonstrates a JDeveloper extension that can be invoked to create 
* a Java file and add it to the currently selected project.

* This wizard can be installed in the gallery and invoked from there.
* When invoked, the wizard opens a Class Wizard dialog, which requests a name 
* for the class. When it is provided the wizard creates a Java program. 
*/
public class HelloX implements Wizard, Addin
{

// 
// Fields
// 

protected String imageName = "HelloX.gif";
protected String wizName = "Hello X Wizard";
protected String prompt = "Greetee:";

private Icon image;
private HelloX instance;
private MenuSpec menuSpec;

// 
// Constructors
// 

/**
* Default constructor. 

* A singleton instance is created when the wizard is loaded at startup.

* This wizard is registered here so that it can be accessed from the
* Tools menu. 
*/

public HelloX() 
{
if ( instance == null )
{
instance = this;
}
}
 

// 
// Methods required by the Wizard interface 
// 

/**
* Performs the wizard's function. This method is called by the IDE when
* the user selects one of the wizard's UI elements.

* This wizard creates a Java file, adds it to the current project, and opens
* it for editing.

* @param context the context of the invocation, which names the current
* project.
* @param params optional arguments.

* @return true if the invocation was successful, false otherwise.
*/

public boolean invoke(oracle.ide.addin.Context context, java.lang.String[] params)
{
if ( !this.isAvailable(context) )
return false;

String greetee = null;
JProject project = (JProject) context.getProject();

// Get the parameter from the user.
greetee = JOptionPane.showInputDialog
(new JDialog(), prompt, wizName, JOptionPane.OK_CANCEL_OPTION);

if ( greetee == null ) 
return false;

// Create the document and the node that represents it.
if ( !createNode(project, greetee) )
return false;

return true;
}
 

/**
* Returns the human-readable name of this wizard.
*/
public java.lang.String getName()
{
return wizName;
}

/**
* Returns the wizard's menu label.
*/
public java.lang.String getMenuLabel()
{
return wizName;
}

/**
* Returns the menu presentation for this wizard.
*/

public MenuSpec getMenuSpecification()
{
if ( menuSpec == null)
{
Icon icon = getIcon();
menuSpec = new MenuSpec(wizName, new Integer((int)'X'), (KeyStroke)null, icon);
}
return menuSpec;
}
 

/**
* Determines the active state of this wizard.
* @param context a record of the current state of the IDE.
* @return true if this wizard is to be activated; false if it is to be 
* inactivated.
*/

public boolean isAvailable(oracle.ide.addin.Context context)
{
Project p = context.getProject();
if ( (p != null) && (p instanceof JProject) )
return true;
return false;
}
 

/**
* Returns a string representation of the wizard. Usually, this should be 
* the same as getName(). 
*/
public String toString()
{
return wizName;
}

/**
* Returns the icon to be used for this wizard in the Object Gallery and 
* Navigator.
* @return an icon if this wizard is to be accessable from the Object Gallery,
* or null if not.
*/

public Icon getIcon() 
{
if (image == null) 
{
image = GraphicsUtils.createImageIcon(
GraphicsUtils.loadFromResource(imageName, this.getClass()));
}
return image;
}
 

// 
// Methods required by the Addin interface 
// 
 

public void initialize()
{
WizardManager wizardMgr = WizardManager.getInstance();
wizardMgr.registerWizard((Wizard)this, true);
}
 

public void shutdown()
{
}

public float version()
{
return 1.0f;
}

public float ideVersion()
{
return Ide.getVersion();
}

public boolean canShutdown()
{
return true;
}

// 
// Other methods
// 
 

/**
* Creates a node representing a Java file.
* @param project the file's project.
* @param greetee the parameterized part of the class.
* @return true if the node was successfully created; false otherwise.
*/

protected boolean createNode
(
JProject project,
String greetee
)
{
String className = "Hello" + greetee;
JavaSourceNode node = null;

// Construct a URL for the class
URL dirURL = getProjectSourceDirectory(project);
if ( dirURL == null )
return false;

URL classURL = URLFactory.newURL(dirURL, className + ".java"); 
if ( classURL == null )
return false;

// Make sure the node doesn't already exist
if ( NodeFactory.find(classURL) != null )
return false;

// Create the node
try
{
node = (JavaSourceNode) NodeFactory.findOrCreate(JavaSourceNode.class, classURL);
project.add(node, true);
node.open();
}
catch (Throwable t)
{
return false;
}

// Create the content
boolean success = createContent(node, project, className, greetee);

if ( !success )
return false;

// Open the document for editing.
EditorUtil.openDefaultEditorInFrame(node);

return true;
}
 

/**
* Creates a Java source file containing the skeleton of a class 
* or interface definition.
* @param node the node that will represent the file.
* @param project the file's project.
* @param className the name of the class or interface.
* @param greetee the parameterized part of the output text.
* @param packageName the body of the file's package statement.
* @return true if the file was successfully created; false otherwise.
*/

protected boolean createContent
(
JavaSourceNode node,
JProject project,
String className,
String greetee
)
{

JotManager mgr = JotManager.getJotManager(project);
JotFile jotFile = mgr.getFile(node.getURL());
String greeting = "\"Hello, " + greetee + "!\"";

if ( jotFile == null )
return false;

// Describe the class
JotClass helloxClass = jotFile.addClass(className);
helloxClass.setModifiers(Modifier.PUBLIC);
helloxClass.setIsInterface(false);

// Create the main method
JotMethod mainMethod = helloxClass.addMethod(null, true, "void", "main");
mainMethod.setModifiers(Modifier.PUBLIC + Modifier.STATIC);
mainMethod.addParameter("String[]", "args");
JotCodeBlock mainCodeBlock = mainMethod.getCodeBlock();
JotMethodCall printlnCall = mainCodeBlock.createMethodCall("System.out", "println");
printlnCall.addArgument(greeting);
mainCodeBlock.addExpressionStatement((JotStatementExpression)printlnCall);

// Write the JOT representation to the file
jotFile.commitFile();

return true;
}
 

/**
* Constructs a URL for a project's source files. 
* @param project A project (.jpr) node.
* @return a URL constructed from the project's source path and default 
* directory.
*/
protected URL getProjectSourceDirectory(JProject project)
{
if ( project == null )
return null;

URLPath prjSrcPath = project.getProjectSourcePath();
URL base = prjSrcPath.getFirstEntry();
String defaultPkg = project.getDefaultPackage();
if ( (base == null) || (defaultPkg == null) )
return null;

String defaultPkgDir = defaultPkg.replace('.', '/');
URL dirURL = URLFactory.newDirURL(base, defaultPkgDir);
return dirURL;
}

}
 
 

Notes: 

When the wizard's New Gallery page or menu is opened, before the wizard is actually selected, the Wizard Manager calls the wizard's getIcon() method to obtain its graphic and call isAvailable() to determine if the icon and name should be displayed as selectable or not. In this case, the generated class file must be added to an existing project, so the current context � the currently selected object � must be a JProject.

When the user selects the wizard's item the Wizard Manager calls its invoke() method. As a typical wizard, Hello X opens a modal dialog to obtain user input � the string greetee � and passes it to the method that will create the class and its node.

To construct the node, the createNode() method creates a URL from the class name (a concatenation of "World" and the greetee parameter supplied by the user), and the project's URL. The class file will be created in the project's directory. 

The content of the class file is Java code, created in the createContent() method using JOT (Java Object Tool). JOT classes represent Java's syntactic elements, such as classes, methods, parameters, and expressions. 

 

4. Optionally, you can add an icon to the project, for use in the wizard menu item. Copy HelloX.gif and paste it in your HelloX directory, in this example <your_hard_drive>:\hello_x\Project\src\oracle\jdev\hellox\. 

 

5. In the Application Navigator, right-click HelloX.java and select Make HelloX.java .

Move your mouse over this icon to see the image

Check the Messages window for a message that the compilation has run without error. If any errors occur, check for cut-and-paste errors. Correct and recompile until the compilation is error-free.

 

6. Select the Hello X project node and choose File | Save All to save all changes in the project.

0&&parent.frames.length) { d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);} if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<(a.length-2);i+=3) if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];} } //-->

Step 3 - Creating the Archive Description File

Before you can deploy an extension, you must create a file jdev-ext.xml which provides JDeveloper with information about how the extension is to be loaded on startup. Only one jdev-ext.xml per project can exist, and it must always be in a directory named meta-inf.
1. Right-click the HelloX project node and select New from the context menu to display the New Gallery dialog.

Move your mouse over this icon to see the image

 

2. From the New Gallery, select General | File to display the Create File dialog .

Move your mouse over this icon to see the image
 

Click OK.

 

3. In the Create File dialog, enter these values:
File Name: jdev-ext.xml .
The archive description file uses this exact name, and it must be in the meta-inf directory in the project.
Directory Name: <your_hard_drive>:\hello_x\Project\src\meta-inf .

Move your mouse over this icon to see the image
 

Click OK to create the file.

 

4. Copy and paste the following XML into jdev-ext.xml to register Hello X with JDeveloper:

<?xml version = '1.0' encoding = 'windows-1252'?>
<extensions xmlns="http://xmlns.oracle.com/jdeveloper/905/extensions">
<feature>
<group name="Samples">
<group name="Hello X">
<extension>
<addin>oracle.jdev.hellox.HelloX</addin>
<gallery>
<name>oracle.jdev.hellox.HelloX</name>
<description>Hello X Wizard.</description>
<help>Create a class that says 'Hello' using a name supplied by you.</help>
<icon>oracle/jdev/hellox/HelloX.gif</icon>
<category>General</category>
<folder>Samples</folder>
</gallery>
</extension>
</group>
</group>
</feature>
</extensions>
 

Notes:
The <gallery> entry gives the name that will appear in the New Gallery, and names the class that implements the Wizard interface. When the New Gallery is opened, the Gallery Manager parses jdev-ext.xml, and when an item is to be displayed, the manager attempts to load it. If the class exists, and implements Wizard, the manager loads the class and calls its default constructor to create and initialize an instance. The instance will persist until JDeveloper is exited, handling all invocation requests

The <addin> entry names the class that implements the Addin interface. When JDeveloper is launched, jdev-ext.xml is read, and all the named addins are loaded, instantiated, and initialized. Any extension that is invoked from the menu or toolbar must be installed as an addin, otherwise the addin menu item or icon will not appear.

 

5. Right-click jdev-ext.xml and select Check XML Syntax. You should see a message in the message log that reports no errors. If errors are reported, look for copy-and-paste errors, correct them, and retest until no errors are reported.

Move your mouse over this icon to see the image

 

6. Select the HelloX project node and choose File | Save All to save all changes.

Step 4 - Deploying the Hello X Wizard

The deployment process packages the wizard in a Java archive file (JAR) and deposits it in a target directory, which you define as the JDeveloper extension directory, so that you can debug Hello X in a second debugger instance of JDeveloper.
1. In the Application Navigator, right-click the Hello X project node and select New.

Move your mouse over this icon to see the image

 

2. From the New Gallery dialog, select General | Deployment Profiles | Jar File.

Move your mouse over this icon to see the image
 

Click OK

 

3. From the Create Deployment Profile dialog, enter hellox.deploy in the Deployment Profile Name field. Use the default value for Directory.

Move your mouse over this icon to see the image
 

Click OK to create the file and display the JAR Deployment Profile Properties dialog. If the dialog does not automatically display, you can right-click hellox.deploy from the Application Navigator and choose Properties .

 

4. Set the following values in Jar Options:
JAR File: <jdev_install>\jdev\lib\ext\hellox.jar .
Compress Archive: unchecked. This is not necessary unless an extension is large.
Include Manifest File: unchecked. This is not necessary unless you are deploying to a version of OC4J (JDeveloper, standalone, or remote) earlier than 9.0.3.

Move your mouse over this icon to see the image


Leave all other default values in JAR Deployment Profile Properties and click OK

 

5. Select the HelloX project node and choose File | Save All to save all changes in the project.

 

6. In the Application Navigator Resources node, right-click hellox.deploy and choose Deploy to JAR File.
The log window should show that deployment has finished without error, and that the hellox.jar archive has been created.

Move your mouse over this icon to see the image

Because you deployed the JAR file to the target directory for all extensions, <jdev_install>\jdev\lib\ext, you do not need to copy the JAR file to that directory.

 


Step 5 - Debugging Hello X


1. In the Application Navigator, right-click the HelloX project node and choose Debug Project.jpr.

Move your mouse over this icon to see the image

 

2. In the Choose Default Run Target dialog, select Hellox.java and click OK.

Move your mouse over this icon to see the image
 

The debuggee process opens with Hello X loaded in a new JDeveloper instance.

 

3. To use the Hello X Wizard, right-click any project node to display the context menu and choose New. (Hello X must be called from a project). 
From Categories, select New | Samples | Hello X Wizard

Move your mouse over this icon to see the image

Click OK.

 

4. In the Greetee dialog, enter a name, for example Kim.

Move your mouse over this icon to see the image

 

5. JDeveloper closes the Greetee dialog and creates a HelloKim class. You should see it in your Hello X project.

Move your mouse over this icon to see the image

Notice that the Hello X wizard is also available by selecting Tools | HelloX Wizard.

 


Summary

Now that you have created and deployed this extension, you can use it with any instance of JDeveloper.

 Move your mouse over this icon to hide all screenshots