Archiv der Kategorie: Eclipse

Articles concernig Eclipse, mostly dedicated to the new Eclipse 4 system

The pain of configuring JSP in Jetty OSGi

As part of a recent project I want to run mitreid connect server embedded within the Elexis-Server Neon.3 based Jetty instance (that is version 9.3.9.v20160517).

Despite the excellent Jetty documentation on this version, I faced major trouble on getting to run this right.

My status / approach was this: First of, I want to run the plain war file provided within a WebAppContext of the Jetty container. This did not prove to be much of a problem, a simple Activator like this achieved this:

@Override
public void start(BundleContext context) throws Exception {
	WebAppContext webapp = new WebAppContext();
	Dictionary props = new Hashtable();
	props.put("war", "lib/openid-connect-server-webapp.war");
	props.put("contextPath", "/openid");
	props.put("managedServerName", "defaultJettyServer");
	context.registerService(ContextHandler.class.getName(), webapp, props);
}

But now the real trouble started – J S P !

The trouble can be broken down into three steps

  1. Configuring the JSP implementation
  2. Setting up the JSTL (Standard Tag Library)
  3. Configuring the WebAppContext to use all of this

Configuring JSP (Apache Jasper implementation)

This is pretty much straightforward, as documented in Using JSPs.
Just one thing is a little hidden – you additionally need apache aries.

Here goes a (hopefully) complete list

      id="javax.servlet.jsp.jstl"
      id="org.apache.aries.spifly.dynamic.bundle"
      id="org.apache.aries.util"
      id="org.eclipse.core.commands"
      id="org.eclipse.core.expressions"
      id="org.eclipse.core.filesystem"
      id="org.eclipse.core.resources"
      id="org.eclipse.jdt.core"
      id="org.eclipse.jetty.apache-jsp"
      id="org.eclipse.jetty.osgi.boot.jsp"
      id="org.eclipse.text"
      id="org.glassfish.web.javax.servlet.jsp.jstl"
      id="org.mortbay.jasper.apache-el"
      id="org.mortbay.jasper.apache-jsp"
      id="org.objectweb.asm"
      id="org.objectweb.asm.commons"
      id="org.objectweb.asm.tree"

Setting up the JSTL (Glassfish approach)

This is where I started to have problems. Documentation says to include org.glassfish.web:javax.servlet.jsp.jstl-1.2.2.jar which did not work out using Java 8. Eclipse complained with

I could track this down and reverted to org.glassfish.web:javax.servlet.jsp.jstl-1.5.0-b03.jar to solve this.

Configuring the WebAppContext to use all of this

At least the dependencies seemed to be satifisied by now – but did it start? No – but
a new Exception occured


2018-01-18 15:21:13,280 WARN  o.e.jetty.servlet.ServletHandler - 
org.apache.jasper.JasperException: Unable to compile class for JSP
	at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:600) ~[org.mortbay.jasper.apache-jsp_8.0.33.jar:2.3]
	at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:363) ~[org.mortbay.jasper.apache-jsp_8.0.33.jar:2.3]
	at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:396) ~[org.mortbay.jasper.apache-jsp_8.0.33.jar:2.3]
...
Caused by: java.lang.NullPointerException: null
	at org.apache.jasper.JspCompilationContext.getTldResourcePath(JspCompilationContext.java:551) ~[org.mortbay.jasper.apache-jsp_8.0.33.jar:2.3]
	at org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:420) ~[org.mortbay.jasper.apache-jsp_8.0.33.jar:2.3]

This post left me with some
hints on what could be the problem. It breaks down to the JettyJasperInitializer#onStartup not being called and some configurations missing.

Some more searches brought me to the embedded-jetty-jsp sample project where this was initialized. (I had to use the non-jetty-annotations approach, as I also use org.eclipse.gemini.naming in the container, already providing a JNDI implementation).

I extracted the JspStarter from the mentioned project, and modified the Activator

webapp.addBean(new JspStarter(webapp.getServletContext().getContextHandler()));

and now it works – the journey continues! Hope this blog spares somebody else some trouble!

JFace Databinding with PojoProperties on Boolean

Consider the following Pojo Foo


public class Foo {
  boolean boolProp;

  public void setBoolProp(boolean boolProp){
    this.boolProp = boolProp;
  }

  public boolean isBoolProp() {
    return boolProp;
  }
}

then you might assume, that you can databind that with master-detail pattern given a SWT.Button with the following code

IObservableValue uiObs = WidgetProperties.selection().observe(button);
IObservableValue prescObs = PojoProperties.value("boolProp", Boolean.class).
    observeDetail(observable);
dbc.bindValue(uiObs, prescObs);

Well this will not work, you actually have to have a method

  public boolean getBoolProp() {
    return isBoolProp();
  }

in your Pojo to make it work.

I am not sure, why this is the case, as one tries to programm according to bean style, where you have the isX and setX for Boolean properties. I am also not sure wether this is different for newer versions of JFace (this is 3.8.0). Just find it worth mentioning, and am hoping for some comments on this 🙂

Oomph and github pull request task lists

After Eds and Eikes nice talk on Oomph at EclipseCon 2014, I decided to give it another try for our Elexis project. Turns out that its a bit tricky to come in.

One thing is that I want to configure the pull requests available in the github repo as tasks within Eclipse, and this is what I did to do so

githubPullRequests

I found out about the correct connector kind when diving into my workspaces .metadata/.mylyn directory having a look at repositories.xml.zip. This also showed me that I have to add the attribute state=open:: in order to have fully configured task lists on the open pull requests.

e4: Updating UI contributions on context switch

During the implementation of a new project, I want to harness the capabilities of the Eclipse application model when it comes to changes in the Eclipse context, or more accurate the de-/activation of context specific handlers.

What does that mean? Lets have a look at the following application model:

contextswitchmodel1 is the global definition of our testCommand, 2 and 3 are perspectives in our application where for the given command a separate handler gets activated due to the context switch from perspectiveA to perspectiveB and vice-versa. 4 is the UI contribution of the command visible to the user in the top window trim.

The resulting application looks like testAppshown on the left hand side. Where the UIContribution 4 is marked with a red arrow. Now the task of the handlers is to toggle between the perspectives and update the UI contribution to either show perspectiveA or perspectiveB.

As described in stackoverflow and the Eclipse forum I did not, at first, find an obvious approach to this (remark in Eclipse 3.x this could be implemented by using an IElementUpdater). After some more analysis I found a way to do so. The source for the following example is certainly available.

Lets fix the example by having a look at HandlerA


public class HandlerA {
    
    @Execute
    public void execute(EPartService partService,
             EModelService modelService, MApplication application) {
        MPerspective perspective = (MPerspective) modelService.find(
                "perspectiveB", application);
        partService.switchPerspective(perspective);
    }

    @Inject
    public void bla(
            @Optional @Active @Named("handler::testCommand") Object value,
            EModelService modelService, MApplication application) {
        if (value == null)
            return;
        List<MHandledItem> findElements = modelService.findElements(
                application, null, MHandledItem.class, null);
        for (MHandledItem mHandledItem : findElements) {
            mHandledItem.setLabel("perspectiveA");
            mHandledItem.setTooltip("perspectiveA now active");
        }
    }
}

The @Execute method does the simple task of toggling the perspective. The updating itself happens in lines 12-23. This method does listen to property changes of handler::testCommand which is the global command (see 1 in the above app model). Each time a context switch happens we get injected the current handler through Object value. So we may act accordingly. Here we act by using the modelService to find all contribution elements subsequently setting a new Label and Tooltip.

If more commands and handlers are in your application you should do a more intelligent search and/or filter on the value to act correct.

This approach, however, is not perfect, as you have to implement this method in both handlers in order to always be able to act upon the change. There are other feasible approaches like creating an Addon where you put the @Inject part, you would have to do this for each command separately, however.

I would prefer to be able to define a class within the MCommand element to put the respective code into which would always be notified in any change that happens related to it. So imagine that a MCommand has an option Class Uri and the respective referenced class could look like this

public class TestCommand {

    @Inject
    EModelService modelService;

    @Inject
    MApplication application;

    @Inject
    public void bla(@Optional @Active MHandler activeHandler,
            @Active MCommand command) {
        if (activeHandler == null)
            return;
        List<MHandledItem> findElements =
                modelService.findElements(
                application, null, MHandledItem.class, null);
        for (MHandledItem mHandledItem : findElements) {
            mHandledItem.setLabel("perspectiveA");
            mHandledItem.setTooltip("perspectiveA now active");
        }
    }
}

Where the injection will happen on change of the activeHandler and I also get the MCommand itself injected. This way one could also efficiently store the given UiContribution elements and limit the searches ….

What do you think? Eager to hear your opinion 🙂

Setting Java for Eclipse on OS X …

It already bothered me for some time, that one constantly seems to have Eclipse running with the wrong Java version. That is, if you’re doing heavy development you might have Java 6, 7 and 8 installed on your machine.

In order to switch the main JVM Eclipse will run with you have to follow these instructions, which involves manually changing the .ini file each time you want to change the version. This is quite cumbersome, so I decided to learn some Apple Automator.

After some insatisfying approaches to generate a service, I generated an application that works as follows:

  1. Drag an OS X Eclipse.app onto it
  2. The application browses all JDK installations in /Library/Java/JavaVirtualMachines and prompts you to select one, which it will then configure within the resp. ini file

The app is completely realized in Automator, with some perl, I had to zip it to distribute it over Dropbox. It is in a very early stage … feedback always welcome 🙂 Here goes a short demo video:

Horizontal extending the application model editor

With this commit the functionality to extend the Application model editor is augmented to allow for horizontal extension of its elements. So what does this mean?

Lars describes in his tutorial how to vertically extend the application model, that is, how to add additional model elements and provide a respective editor for it. But what if I want additional editing capabilities to already existing model elements like e.g. the command element?

This is where the new extension point org.eclipse.e4.tools.emf.ui.editors.editorTab comes into play. The following image shows an example of the current usage within the Écrit project:

horizontal extension point with and without
horizontal extension point with and without

We added the possibility to augment existing model elements with additional documentation artifacts – but this will become part of another blog (series) 😉

Back to the extension point. In order to use it you have to first extend this new extension point, directing it to a class extending org.eclipse.e4.tools.emf.ui.common.AbstractElementEditorContribution:

editorTab EP
editorTab EP

This class may look like

import org.eclipse.core.databinding.observable.value.WritableValue;
import org.eclipse.core.resources.IProject;
import org.eclipse.e4.tools.emf.ui.common.AbstractElementEditorContribution;
import org.eclipse.e4.ui.model.application.commands.MCommand;
import org.eclipse.emf.databinding.EMFDataBindingContext;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.swt.widgets.Composite;

public class blaClass extends AbstractElementEditorContribution {

@Override
public void createContributedEditorTab(Composite arg0,
EMFDataBindingContext arg1, WritableValue arg2, EditingDomain arg3,
IProject arg4) {
// create the editor tab in here
}

@Override
public Class<?> getContributableTo() {
return MCommand.class;
}

@Override
public String getTabLabel() {
return "myNewTab";
}
}

The getContributableTo denotes to what model elements the editorTab will be added (this is determined as you returned Class must be instanceof).

If you want to have a look at a more specific example, take a look at the Écrit implementation of the extension point.

Questions, comments? 🙂

Exporting model element ids

In order to address model elements out of the application model itsef, and out of contributing classes, the resp. model element id is used. During development you often run into errors because of wrong id strings.

To mitigate this problem a new action, called  Export Model Ids is now available within the e4 tooling starting with this build.

Popup-Menu Command Export Element Id

On execution it selects all the element ids available within the application model, and presents it to the user:

Export Id Handler Dialog

In this table you see the type of element, the static key it is gonna have in the resulting java class, and the original id. Currently the key is built out of the element type and the element id.

After execution you should find a java file called AppModelId.java, probably containing some errors due to you using duplicate ids, such as in the following image:

ExportIdHandler OutputClass AppModelId.java

There are several things I would like to change to this feature, but it seems a good start – thanks a lot to Wim for the feedbacks and reviews!

Things I would like to add/change in the future

  • make the output class, package and project selectable (currently this would introduce too much dependencies)
  • care for double occuring ids
  • make subtrees of the application model exportable (currently the whole app model ids are exported)
  • perform automatically configurable update of the target file(s)
  • remove dependency to org.eclipse.jdt.core

If you have any other feedback or comments, please put them on here!

Programmatically load an Application.e4xmi

In case you were wondering or struggling, just like me, how one could possibly load an Application.e4xmi file out of a standalone Java application, here goes some code for you 🙂

import org.eclipse.e4.ui.internal.workbench.E4XMIResourceFactory;
 import org.eclipse.e4.ui.model.application.MApplication;
 import org.eclipse.e4.ui.model.application.impl.ApplicationPackageImpl;
 import org.eclipse.emf.common.util.URI;
 import org.eclipse.emf.ecore.resource.Resource;
 import org.eclipse.emf.ecore.resource.ResourceSet;
 import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;

public class LoadAppModel {

private static ResourceSet resourceSet = new ResourceSetImpl();

public static void main(String[] args) {
 ApplicationPackageImpl.init();
 URI uri = URI
 .createURI("file:///Users/marco/git/pharmacy_at/at.medevit.ecrit.pharmacy_at.application/Application.e4xmi");

resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap()
 .put("e4xmi", new E4XMIResourceFactory());

Resource res = resourceSet.getResource(uri, true);
 MApplication app = (MApplication) res.getContents().get(0);
 System.out.println(app.getElementId());
 }
 }

res.unload();

Be sure to include all the required bundles, especially in the OSGI context.

Update I just came up to a nasty problem: If you repeatedly iterate your application model, while modifying it, you need to be sure to unload the model each time you are done, otherwise lazy loading will not pick up the changes, as the model is already loaded.

To depict this I added the unload method to the code sample.