We had to build an Eclipse RCP application where SQL statements could be edited. At first, we used a StyledText widget to do this. Soon, we were in need of extra features like syntax coloring, content assist etc. Why not use a ‘ready to use’ SQLEditor to open a SQL file you say? Well, we wanted to ’embed’ the area in our own editor. The SQL area should be part of the editor and not the only thing in the editor!

After a while we discovered a normal StyledText was not the way to do this. After some investigation we found a widget which fits our needs perfectly.. The SQLStatementArea widget which is part of the Eclipse Data Tools Platform (DTP). After installing all necessary plugins, coding could begin..

The SQLStatementArea widget can be used like any other widget in a Editor.

ISQLSourceViewerService viewerService = new CustomSQLSourceViewerService();
SQLStatementArea sta = new SQLStatementArea(this, SWT.BORDER, viewerService, true);
sta.setEditable(true);
sta.setEnabled(true);
  • this: the SWT Composite where the area should be in
  • SWT.BORDER: we want a border to be visible, other styles can be added as usual
  • viewerService: an instance of a class implementing ISQLSourceViewerService (talk about this in a minute)
  • true: when this is true, line numbers are visible

When instantiating the SQLStatementArea a class implementing ISQLSourceViewerService is needed as mentioned earlier. In this class a help method needs to be implemented which will define the PartitionScanner for the document. This method determines where the text has to be scanned for.

This is the code of the method we used for this class:

@Override
public void setUpDocument(IDocument doc, String dbType) {
SQLPartitionScanner sqlPartitionSanner = new SQLPartitionScanner();
if(doc instanceof IDocumentExtension3)
{
IDocumentExtension3 extension3 = (IDocumentExtension3) doc;
FastPartitioner _partitioner = new FastPartitioner(sqlPartitionSanner, new String[]
{
SQLPartitionScanner.SQL_CODE,
SQLPartitionScanner.SQL_COMMENT,
SQLPartitionScanner.SQL_MULTILINE_COMMENT,
SQLPartitionScanner.SQL_STRING,
SQLPartitionScanner.SQL_DOUBLE_QUOTES_IDENTIFIER
});
_partitioner.connect(doc);
extension3.setDocumentPartitioner(ISQLPartitions.SQL_PARTITIONING,     _partitioner);
}
}

Next in line is the SourceViewerConfiguration. This class is responsible for syntax coloring, content assist etc. In our application we’ve used the code from here, because it is more advanced and extensive (multi-line comments for example). However , the code in the available plugins is sufficient for this tutorial. The configuration class to use for a SQL configuration is the SQLSourceViewerConfiguration which can be found in the org.eclipse.datatools.sqltools.sqlbuilder.views.source package.

SQLSourceViewerConfiguration sqlSourceViewerConfiguration = new SQLSourceViewerConfiguration();
sta.configureViewer(sqlSourceViewerConfiguration);

There are still a few things that need to be added in order for the SQLStatementArea to work. As most widgets, it needs a layoutdata, but it also needs a document which holds the actual input. Because were going to add databinding later, we’re setting up an empty document for now.

sta.setLayoutData(new GridData(GridData.FILL_BOTH));
document = new Document();
document.set("");
sta.getViewer().setDocument(document);

Our next step is to add databinding so the text is displayed correctly and the object is updated immediately  This is easy because the SQLStatementArea holds a StyledText widget which we can use to create the binding. When you’re not familiar with databinding you can check out this great tutorial or just set the text of the document for now (instead of empty).

IObservableValue observeTextObserveWidget = SWTObservables.observeText(sta.getViewer().getTextWidget(), SWT.Modify);
IObservableValue sqlSql_statementObserveValue = EMFEditProperties.value(editingDomain, Literals.DOCUMENT_SQL_STATEMENT__SQL_STATEMENT).observe(sql);
bindingContext.bindValue(styledTextStatementObserveTextObserveWidget, sqlSql_statementObserveValue, null, null);
  • editingDomain: we’re connecting the binding to our editingdomain for undo/redo functionality and dirty state (use EMFProperties when not using an editingdomain)
  • sql: the EMF object which holds our SQL statement

When running the application, the result is an editor which holds a great area for editing SQL.

SQLStatementArea integrated in Eclipse Editor

SQLStatementArea integrated in Eclipse Editor

The only thing is, when hitting CTRL+SPACE now, content assist doesn’t work. This is because we have to ‘bind’ the content assist of our SQLStatementArea with the Eclipse content assist.

handlerService = (IHandlerService) editor.getSite().getService(IHandlerService.class);
IHandler cahandler = new AbstractHandler() {
public Object execute(ExecutionEvent event) throws ExecutionException {
sta.getViewer().doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS);
return null;
}
};
if(contentAssistHandlerActivation != null){
handlerService.deactivateHandler(contentAssistHandlerActivation);
}
contentAssistHandlerActivation = handlerService.activateHandler(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS,
cahandler);

Now, when starting the application again, content assist will work!

SQLStatementArea integrated in Eclipse Editor with content assist

SQLStatementArea integrated in Eclipse Editor with content assist

When using this in an application we recommend to use the code mentioned earlier or to write your own. This way you can have far more keywords, multi-line comments, content formatting (uppercase/lowercase) and so on. But we hope this tutorial gives you a great start!

In many back-office applications, in Belgium and The Netherlands at least, Oracle Forms is a much seen framework. Praised for the stability and speed of development Oracle Forms was a major player in it’s time. However, today, these Oracle Forms applications get more and more outdated and end users and companies are requiring 21st century features like web service-, desktop- and social media-integration or an intuitive and feature-packed UI.

Often, companies that own such forms apps are told to migrate to another framework like Oracle ADF, JEE or .NET. I ‘d like to add another framework to the list: Eclipse RCP.

Eclipse RCP is an very modern, widely used and stable framework which fulfills all of today’s requirements for applications. Why Eclipse RCP?

During the Forms Modernization seminar organized by iAdvise, I will give a demo on how to integrate an existing Oracle Forms application inside an Eclipse RCP application allowing a very smooth and cost-effective transition from Oracle Forms to Eclipse RCP by retaining parts of the old application inside the new one.

Screenshot of an Oracle form inside an Eclipse RCP view

The demo will show:

  • Oracle Forms inside an Eclipse RCP page
  • how to use Eclipse RCP commands to control Oracle Forms (enter-query, execute-query, save,…)
  • how to pass values from Eclipse RCP to Oracle Forms and vice versa
  • master-detail views (Oracle Forms being the master)
  • how to use Oracle Forms commands to show Eclipse RCP views and dialogs

The seminar is held on the 6th of June, 2011 at Hof ter Delft (www.hofterdelft.be)

If you like to attend please register here

Goal:

For an RCP application which we are building at the moment we were in need of a Tree with checkboxes. It ‘s not just a question of using the JFace CheckboxTreeViewer because we wanted to control on which level in the tree the checkbox was shown. As you know, the CheckboxTreeViewer shows a checkbox on every level.

An added bonus is that now, we can change the look of the checkbox by supplying our own images.

After some investigation, I found this solution to be the easiest:

Solution:

1.
The first thing you need are two custom icons, one for a checked and one for an unchecked checkbox. I’ve used these icons for this example:

 

2.
Create a JFace TreeViewer with one TreeViewerColumn and three TreeItems (don’t use TreeItems with a TreeViewer in your application, use ContentProvider and LabelProvider instead). Add the unchecked icon to the TreeItems on the second level.

Example:

Composite compositeExample = new Composite(composite, SWT.NONE);
compositeExample.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
TreeColumnLayout tcl_compositeExample = new TreeColumnLayout();
compositeExample.setLayout(tcl_compositeExample);

TreeViewer treeViewerExample = new TreeViewer(compositeExample, SWT.BORDER | SWT.FULL_SELECTION);
treeExample = treeViewerExample.getTree();
treeExample.setHeaderVisible(true);
treeExample.setLinesVisible(true);

TreeViewerColumn treeViewerColumnName = new TreeViewerColumn(treeViewerExample, SWT.NONE);
TreeColumn trclmnName = treeViewerColumnName.getColumn();
tcl_compositeExample.setColumnData(trclmnName, new ColumnWeightData(100, ColumnWeightData.MINIMUM_WIDTH, true));
trclmnName.setText("Name");

TreeItem trtmParent = new TreeItem(treeExample, SWT.NONE);
trtmParent.setImage(ResourceManager.getPluginImage("your_plugin_name", "your_image_name"));
trtmParent.setFont(FontConstants.FONT_NORMAL);
trtmParent.setText("Parent");

TreeItem trtmChild = new TreeItem(trtmParent, SWT.NONE);
trtmChild.setFont(FontConstants.FONT_NORMAL);
trtmChild.setImage(imgUnChecked);
trtmChild.setText("Child");

TreeItem trtmChild_1 = new TreeItem(trtmParent, SWT.NONE);
trtmChild_1.setFont(FontConstants.FONT_NORMAL);
trtmChild_1.setImage(imgUnChecked);
trtmChild_1.setText("Child");
trtmParent.setExpanded(true);

Once you have filled your tree and have a screen similar to below, you can add the real functionality.

3.
Now the icon has to change when the user clicks on it. We can achieve this by adding the following MouseListener to the tree. It will listen to clicks inside the tree and compare it with the items inside the tree. Once you know the clicked item, you can change his image.

tree_1.addMouseListener(new MouseListener(){

	@Override
	public void mouseDoubleClick(MouseEvent e) {
	}

	@Override
	public void mouseDown(MouseEvent e) {
		for(TreeItem item : tree_1.getSelection()) {
			if(item.getImage() != null) {
				if((e.x > item.getImageBounds(0).x) && (e.x < (item.getImageBounds(0).x + item.getImage().getBounds().width))) {
					if((e.y > item.getImageBounds(0).y) && (e.y < (item.getImageBounds(0).y + item.getImage().getBounds().height))) {
						setChecked(item);
					}
				}
			}
		}
	}

	@Override
	public void mouseUp(MouseEvent e) {
}});

private void setChecked(TreeItem item) {
	if(item.getImage().equals(imgUnChecked)) {
		item.setImage(imgChecked);
	}
	else {
		item.setImage(imgUnChecked);
	}
}

4.
Run you program and click on the icons, you will see that they really act like a checkbox. Now all you have to do is customize it!

Apologies for the long delay on the promised blog post about getting RAP on your Tomcat. We promised this at our Eclipse Demo camp presentations a few times, but we have been quite busy with Eclipse projects for our clients. The delay has been so great that this method is now nearly outdated thanks to Holger Staudacher’s RAP War deployment tool. So I am splitting this post in two parts. Part 1 is the originally planned post about the old way and part 2 will handle the exiting new way of the War deployment system. So without further ado I give you ‘getting RAP on your Tomcat part 1’.

Getting RAP on your Tomcat

1. Just try getting the Equinox bridge to work.

I have been a RAP enthusiast from the moment my boss introduced it to me and I had an RCP training. It is a great way to single source most web-based applications or applications for normal clients.

There is just one thing that RAP is not easy about and that is deploying it on a web server in a servlet. There are several reasons for this. First off, you need to get then OSGi running in the servlet. And then your application. At which point you realise that RAP is developing so fast that most of what you find out there is outdated. Therefore the need arises for a system to deploy it to your web application server. This need created the GOOGLE Summer Code project 2010 “WAR deployment for RAP/Equinox based applications”. You can find the project draft at here & and here and there is a discussion on the Eclipse forums as well here.

Now, it is great news that there is going to be a tool for this tedious task, but the project does not start before May 24 2010. This means that for now we are still bound to the old ways. And this may be problematic if your basis is out of date. Then you can have a problem like this:

To deal with this issue, you can create a new team project (extension psf) with the following text in it:

<?xml version=”1.0″ encoding=”UTF-8″?>

<psf version=”2.0″>

<provider id=”org.eclipse.team.cvs.core.cvsnature”>

<project reference=”1.0,:pserver:dev.eclipse.org:/cvsroot/tools,org.eclipse.orbit/javax.servlet,javax.servlet,v2_5″/>

<project reference=”1.0,:pserver:dev.eclipse.org:/cvsroot/rt,org.eclipse.equinox/server-side/bundles/org.eclipse.equinox.http.registry,org.eclipse.equinox.http.registry”/>

<project reference=”1.0,:pserver:dev.eclipse.org:/cvsroot/rt,org.eclipse.equinox/compendium/bundles/org.eclipse.equinox.http.servlet,org.eclipse.equinox.http.servlet”/>

<project reference=”1.0,:pserver:dev.eclipse.org:/cvsroot/rt,org.eclipse.equinox/server-side/bundles/org.eclipse.equinox.http.servletbridge,org.eclipse.equinox.http.servletbridge”/>

<project reference=”1.0,:pserver:dev.eclipse.org:/cvsroot/rt,org.eclipse.equinox/server-side/bundles/org.eclipse.equinox.servletbridge,org.eclipse.equinox.servletbridge”/>

<project reference=”1.0,:pserver:dev.eclipse.org:/cvsroot/eclipse,equinox-incubator/org.eclipse.equinox.servletbridge.feature,org.eclipse.equinox.servletbridge.feature”/>

<project reference=”1.0,:pserver:dev.eclipse.org:/cvsroot/eclipse,org.eclipse.update.configurator,org.eclipse.update.configurator”/>

</provider>

</psf>

Note: if there is a question about user name pass use the username anonymous

Now, normally this would be enough. But the RAP team came up with a great automated method for creating a WAR archive. So we are going to import it as well. You can use the following TEAM project:

<?xml version=”1.0″ encoding=”UTF-8″?>

<psf version=”2.0″>

<provider id=”org.eclipse.team.cvs.core.cvsnature”>

<project reference=”1.0,:pserver:dev.eclipse.org:/cvsroot/rt,org.eclipse.rap/releng/org.eclipse.rap.demo.feature,org.eclipse.rap.demo.feature”/>

</provider>

</psf>

Your Eclipse should look something like this (there may be a discrepancy if you have a RAP application there too):

Copy the org.eclipse.rap.demo feature as org.eclipse.equionx.servlet.new.feature. Copy the feature.xml from the old org.eclipse.equionx.servlet.feature so that you have the basis. Once you have done this, unfold the templates folder – it needs some editing. First off, open the web.xml – we need to remove <!– –> from the following text:

<init-param>

<param-name>commandline</param-name>

<param-value>-console</param-value>

</init-param>

This will enable the OSGi console, provided that you successfully deployed the WAR file to a server in its console. You can add a port number after ‘–console’ if you want to telnet to it. Next, you change the false to true for the following part:

<init-param>

<param-name>enableFrameworkControls</param-name>

<param-value>true</param-value>

</init-param>

This will enable the controls of the framework trough the web interface. You can read more about it at here.

Now remove the following parts:

<!– Enable multi-language support for the extension registry –>

<init-param>

<param-name>commandline</param-name>

<param-value>-registryMultiLanguage</param-value>

</init-param>

<!– Framework Controls could be useful for testing purpose, but

we disable it in RAP environment per default –>

Now go to your Eclipse folder, open launch.ini and change it as follows:

osgi.parentClassloader=app

osgi.contextClassLoaderParent=app

Note: you can read more about this in the Eclipse FAQ No. 105

Next thing to do is to edit the Ant script in the script folder. Find the property webapp.name and features and change them to the following:

<property name=”webapp.name” value=”bridge” />

<property name=”features” value=”org.eclipse.equinox.servletbridge.new.feature” />

Now you can run the Ant script by going to Run>External Tools>External Tools configuration. Here you create a new launch configuration for the Ant builder. Go to the JRE tab and change the Runtime JRE to “Run the same JRE as Workspace”. This will enable the Ant script to use the PDE.Builder to build the bundles. Click on Run. The JRE will start and you will see the PDE.Export running. You will have to refresh the feature project after that. Next you will see a BUILD folder been added. Unfold the scr folder and find ConfigIniCreator.java file. Open it and change the file location to:

{Projectfolder}\\org.eclipse.equinox.servletbridge.new.feature\\build\\bridge\\WEB-INF\\eclipse\\plugins

Save the changes and run it. You will see the following output:

#Eclipse Runtime Configuration File

osgi.bundles=  org.eclipse.equinox.common@2:start,\

org.eclipse.equinox.http.registry@start,\

org.eclipse.equinox.http.servletbridge@start,\

org.eclipse.equinox.http.servlet@start,\

org.eclipse.equinox.registry@start,\

osgi.bundles.defaultStartLevel=4

Copy this and go to build>bridge>WEB-INF>eclipse>configuration folder. Edit the config.ini file and paste in the generated output, Save it.

Now we have everything we need in a War file, it is just not in there it. Use any archive application you want – remember to use zip compression. Rename the zipped file to bridge.war and you can congratulate yourself: you now have a Web Application Archive that is ready to be deployed in your servlet server.

In our case, we used a Tomcat 6.0 and started it up manually in Windows so we could see the console. The result should look close to this:

Well done! You now have the OSGi framework running in a servlet. Now we are going to apply it to a RAP application.


2. Getting your RAP project on the Tomcat.

First, copy the org.eclipse.equionx.servlet.new.feature and rename it any way you want.

A small reminder: if you are single sourcing as I do and you set every RCP and RAP part to optional, then this manual will not work. Before you make your product, check all your plugins and set the optional flag off your RAP dependencies so you can actually validate dependencies.

In the feature, we add org.eclipse.rap.ui. Now we create a new product file through file>new>product configuration. Set the product configuration to feature – it should look similar to this:

Go to the dependencies page and add the feature you created. Press the validate button.

You will see this window:

You can see that there are some dependencies missing, among them javax.servlet and javax.servlet.http package. You want to be missing only those two, so add any other missing constraints to you have the whole basic framework of RAP implemented. Add you application plugin and keep reapeating the validation process until all the plugins you see as missing are javax.servlet and javax.servlet.http constraint only. There is one exception to this rule: org.eclipse.equinox.http.servletbridge wants the org.eclipse.equinox.servletbridge. You can chose to ignore this.

Once you have tackled the dependencies, you can run the Ant script again and zip the created WEB-INF to a zip/war file. Before you deploy this, undeploy bridge.war if you have not done it already. Then deploy the War. If you want to put this on a production server, you will have to change the following in the web.xml of your deployable War so it will use less resources and response a lot faster:

<!—

<init-param>

<param-name>commandline</param-name>

<param-value>-console</param-value>

</init-param>

–>

 

<init-param>

<param-name>enableFrameworkControls</param-name>

<param-value>false</param-value>

</init-param>

There you have it, as you can see the old way was quite long and tedious so I’m grateful for  Holger Staudacher’s RAP War deployment tool more on this great tool soon in Part 2.

The First Eclipse Democamp organized by Smartapps and Industrial TSI is a fact. It was a cold and wet night, but fortunately the snow was gone and almost everyone made it in time for the first presentation. With over thirty attendees, we can certainly say the Eclipse DemoCamp Antwerp 2010 was a success.

In a room full Eclipse enthusiasts it was difficult to get everyone onto their seats. The drinks and appetizers were still very popular, but after a short intro of the organizers Tom Bauwens/Ief Cuynen and Yuri Kok, everybody was paying attention and the first speaker began his presentation.  It is sad to say that Oliver Wolf couldn’t make it due to the weather in Germany, but we hope we can welcome him next time to share with us some great information.

Antwerp DemoCamp 2010 (1)
Ief Cuynen (Smartapps) and Yuri Kok (Industrial TSI) gave the intro


The line up looked as followed:

1.      19:15 – 19:30 Ralph Mueller, Eclipse Foundation: “You know the past,can you guess the future of Eclipse?”

Ralph Mueller kicked this camp of and talked about the essence of the Eclipse foundation and in particular their core business and the size of the foundation.

DemoCamp Antwerp 2010 (2)
Ralf Mueller about the Eclipse foundation


2.      19:00 – 19:15 Mike Milinkovich, Eclipse Foundation: KEYNOTE

In 15 minutes, Mike Milinkovich showed us the Eclipse marketplace. The marketplace is there for people who search plugins or want to share their own products/code.


DemoCamp Antwerp 2010 (3)

Mike Milinkovich about the Eclipse Marketplace


3.      19:30 – 20:00 Ralf Sternberg, EclipseSource: A talk from the Eclipse Summit 2010: “A look ahead at RAP: what’s new now and will be noteworthy in the future”

Ralf Stenberg is one of the actual creators of Eclipse RAP and he showed us the future of RAP as well as some of the cool new features RAP 1.4 has to offer. It gave a good overview of the new possibilities.

DemoCamp Antwerp 2010 (4)
Ralf Sternberg presented the new features of RAP 1.4


4.      20:30 – 21:00 Oliver Wolf, Product Manager and Architect at SOPERA GmbH: “SOA at Eclipse”

5.      21:00 – 21:30 Wim Jongman, Industrial-TSI: Eclipse Mashup: How we use Eclipse Technology to stay ahead.

The last speaker of the evening was Wim Jongman. He showed us what techniques they use for application development. RAP, EMF, BIRT all past the revue and it was great to see how these techniques are used in real life.

DemoCamps Antwerp 2010 (5)
Wim Jongman (on the right) preparing his presentation


At about 22:15 the presentations were finished and the evening was discussed over a drink. It was a fun and informative event and we hope everybody enjoyed it. We want to thank all speakers for their time and enthusiasm and we hope we can welcome everyone next time.

DemoCamp Antwerp 2010 (6)
Discussing the evening over a drink

Found a good article of how to access resource files from your Eclipse Plugin which we all sometimes need:
Check it out

Making the view selector available for the user in a RCP/RAP application is quite easy. For this small example we will use the RCP mail demo.

To create the project, select FileNewProjectPlug-in Project, and use benl.smartapps.maildemo as the project name.

Click on Next button.

It’s important that you set the Rich Client Application to yes. After clicking Next, select the RCP Mail Template and finally click the Finish button. This will result in Eclipse creating a new project based on the RCP Mail Demo. In the screen it opens you can press Launch an Eclipse application.

After clicking the launch link you will see following application

As you can see the application is missing the Perspective selector we usually have in Eclipse. To make it visible is quite easy. In the project find the ApplicationWorkbenchWindowAdvisor in the SRC folder.

If you open this class you will see the function preWindowOpen() function. This function will call in the constructor of the Workbench Window. Use this method to set options such as hiding the menu bar, etc.

The code that is already filled in under this function looks like the following:

Now we add the following code:

Now if we leave it as  is, we would get the Perspective selector in our workbench. However, we want to be sure that the user knows what it means. So after saving our changes we go back to our plugin.xml and go to the Extensions tab. Here we expand the  org.eclipse.ui.perspectives extension and select the RCP Perspective. The problem is that RCP Perspective doesn’t inform the end user what it is or what it will do. So when setting a perspective in the Extensions it is very important that the name field is filled in with a clear and understandable name which will inform the end user what kind of function it is. In our little example we will set it to Mail.

If we run the application now after saving our changes the application will look something like this:

The red marking shows what we just added. Now we can style this to look and make it look a bit more advanced.

First, we will give the view its own icon so that it’s more distinctive then the default icon perspective gives. We select the Mail perspective in the Extension tab. Choose your icon via the browse button or just type it in.

Note: ico files are not fully supported in Eclipse RAP.


Now we can do the customization of the look and feel trough 2 methods one of them is creating the plugin_customization.ini or you can do it hardcoded trough the ApplicationWorkbenchWindowAdvisor . Because we’re demonstrating that it can be done in RCP and RAP project this example will use the ApplicationWorkbenchWindowAdvisor so that it can be used in both projects. You can choose to use both method and creating a fragment file for the RAP project. For more information about using the plugin_customization.ini file you can read the article here.

So nowopen the ApplicationWorkbenchWindowAdvisor again and we can play a bit with the IWorkbenchPreferenceConstants.

For now we edit the code a bit like this:


Note: The IWorkbenchPreferenceConstants.SHOW_TRADITIONAL_STYLE_TABS does not work for RAP applications.

You can look up more settings on the IWorkbenchPrefereceConstants in the RCP api. The above  settings will result in the following:

Now we need to set the default perspective. To do that we need to implement the getInitialWindowPerspectiveId function. Go back to the Extensions tab of the plugin.xml.

Here you can see the id of the Extensions:

To be sure that the ID is also known in the Perspective click on the class link. The Eclipse IDE will now open the perspective class. Here you can see the ID of the perspective as well and it should match the ID you saw in the Extension Element Details.

First, we have to set the private static final String PERSPECTIVE_ID. The ID will be the ID of the Perspective Extension you want as default. So in our case this would be benl.smartapps.maildemo.perspective. Then we add the public String getInitialWindowPerspectiveId() returning the PERSPECTIVE_ID. This would result in the following code:

Now the application will always open the default perspective by default if the user has not saved the state of the workbench.