Skip to main content

Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Using Spring with XWT"

(With fragments)
(With fragments)
Line 463: Line 463:
  
 
You can find fragment sample which configure SpringCLRFactory into the  '''org.eclipse.e4.xwt.springframework.config.springclrfactory''' fragment .
 
You can find fragment sample which configure SpringCLRFactory into the  '''org.eclipse.e4.xwt.springframework.config.springclrfactory''' fragment .
 +
 +
=== Debug ===
 +
 +
You can debug the '''org.eclipse.e4.xwt.springframework bundle''' with standard OSGi Trace.

Revision as of 08:45, 8 August 2010

Introduction

Work is underway to integrate XWT with Spring and Spring Dynamic Module to declare the CLR classes used into XWT file with XML Spring file.

See (for the moment) Bug 320405. Attached to this bug are zips containing bundles

  • org.eclipse.e4.xwt.springframework: bundle of XWT Spring support.
  • org.eclipse.e4.xwt.springframework.tests : Tests (Main/JUnit) of XWT Spring support.

Samples with NO OSGi context :

  • org.eclipse.e4.xwt.springframework.sample : simple sample to declare CLR as Spring bean.
  • org.eclipse.e4.xwt.springframework.sample2 : simple sample to declare CLR as Spring bean which use Spring DI to use a service.

Samples with OSGi context :

  • org.eclipse.e4.xwt.springframework.osgi.sample : simple sample to declare CLR as Spring bean.
  • org.eclipse.e4.xwt.springframework.osgi.sample2 : simple sample to declare CLR as Spring bean which use Spring DI + Spring DM to use a service.
  • org.eclipse.e4.xwt.springframework.osgi.services : bundle which provides HelloService.

CLR Class

Before explaining Spring support for XWT, it's interesting to understand how CLR Java class are managed with x:Class and x:ClassFactory.

CLR with x:Class

The Event Handling sample show you how XWT file can be linked to a Java CLR (Common Language Runtime) class to manage for instance event handler of the UI with Java code by using x:Class attribute :

<Shell xmlns="http://www.eclipse.org/xwt/presentation"
    xmlns:x="http://www.eclipse.org/xwt"
    x:Class="ui.EventHandler">
    <Shell.layout>
       <GridLayout/>
    </Shell.layout>
    <Button text="Click Me!" SelectionEvent="clickButton">
    </Button>
</Shell>

The declaration x:Class="ui.EventHandler" means that the UI is linked to the Java class ui.EventHandler :

package ui;
 
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Button;
 
public class EventHandler {
 
    protected void clickButton(Event event) {
        Button button = (Button )event.widget;
        button.setText("Hello, world!");
    }
}

When the button gets selected, the method clickButton is invoked to change the Button text to "Hello, world!".

CLR with x:ClassFactory

You can do the same thing (link a CLR class with XWT) with CLR factory :

<Shell xmlns="http://www.eclipse.org/xwt/presentation"
    xmlns:x="http://www.eclipse.org/xwt"
    x:ClassFactory="ui.EventHandlerFactory">
    <Shell.layout>
       <GridLayout/>
    </Shell.layout>
    <Button text="Click Me!" SelectionEvent="clickButton">
    </Button>
</Shell>

The declaration x:ClassFactory="ui.EventHandlerFactory" means that the UI is linked to the Java class which is provided by ui.EventHandlerFactory :

package ui;
 
import org.eclipse.e4.xwt.ICLRFactory;
 
public class EventHandlerFactory implements ICLRFactory {
    public Object createCLR(String args) {
        return new ui.EventHandler();
    }
}

This CLR factory implements org.eclipse.e4.xwt.ICLRFactory which returns an instance of ui.EventHandler which is the CLR class described below.

Spring support for XWT

The bundle org.eclipse.e4.xwt.springframework is the Spring support for XWT which implements org.eclipse.e4.xwt.ICLRFactory to declare CLR Class with bean Spring. It's possible to use this Spring support :

Using Spring with XWT

To declare CLR class with bean Spring (not OSGi context) you must

Add JAR/Dependencies

XWT Dependencies :

  • org.eclipse.swt;bundle-version="3.6.0",
  • org.eclipse.e4.xwt;bundle-version="0.9.1",
  • org.eclipse.e4.xwt.springframework;bundle-version="0.9.1",
  • com.ibm.icu;bundle-version="4.2.1"


Spring JAR :

  • org.springframework.beans-2.5.6.A.jar
  • org.springframework.context-2.5.6.A.jar
  • org.springframework.core-2.5.6.A.jar
  • com.springsource.slf4j.api-1.5.0.jar
  • com.springsource.slf4j.org.apache.commons.logging-1.5.0.jar
  • com.springsource.slf4j.log4j-1.5.0.jar
  • spring-target-platform/log4j.osgi-1.2.15-SNAPSHOT.jar

Log4j

Create log4j.properties into src folder :

log4j.rootLogger=info, con
log4j.appender.con=org.apache.log4j.ConsoleAppender
log4j.appender.con.layout=org.apache.log4j.PatternLayout
log4j.appender.con.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

Declare Spring bean CLR

Declare your CLR class with bean into XML file Spring. To do that create a XML Spring file ui-context.xml into ui package like this :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
 
  <bean name="myUI" class="ui.EventHandler" scope="prototype">
  </bean>
 
</beans>

scope attribute must be settted to prototype in order to create an instance of EventHandler each time XWT file is opened.

Implements Spring CLRFactory

Implements ICLRFactory wich use a XML Spring file to retrieve CLR bean. To do that you can extends and implkements org.eclipse.e4.xwt.springframework.AbstractSpringCLRFactory :

package ui;
 
import org.eclipse.e4.xwt.ICLRFactory;
import org.eclipse.e4.xwt.springframework.AbstractSpringCLRFactory;
import org.eclipse.e4.xwt.springframework.CLRFactoryParameters;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
public class MySpringCLRFactory extends AbstractSpringCLRFactory {
 
  public static final ICLRFactory INSTANCE = new MySpringCLRFactory();
 
  private ApplicationContext applicationContext = null;
 
  @Override
  protected ApplicationContext getApplicationContext(final String properties, CLRFactoryParameters propertiesMap) {
    if (applicationContext == null) {
      applicationContext = new ClassPathXmlApplicationContext("ui/ui-context.xml");
    }
    return applicationContext;
  }
}

To avoid loading XML Spring file ui-context.xml each time that XWT use our Spring CLR Factory you must :

  • cache the ApplicationContext (applicationContext fields manage that).
  • MySpringCLRFactory define a singleton (INSTANCE) which we will use into x:ClassFactory.

Set the x:ClassFactory

Create XWT file ui.xwt into ui package like this :

<Shell xmlns="http://www.eclipse.org/xwt/presentation"
    xmlns:x="http://www.eclipse.org/xwt"
    x:ClassFactory="ui.MySpringCLRFactory.INSTANCE bean=myUI">
    <Shell.layout>
       <GridLayout/>
    </Shell.layout>
    <Button text="Click Me!" SelectionEvent="clickButton">
    </Button>
</Shell>

You can notice that x:ClassFactory is used to define the Spring Factory :

  • ui.MySpringCLRFactory.INSTANCE define the singleton Spring factory.
  • bean=myUI define the bean of the CLR.

Test and run it

Create UI Java Class test wich open teh ui.xwt file :

package ui;
 
import java.net.URL;
 
import org.eclipse.e4.xwt.IConstants;
import org.eclipse.e4.xwt.XWT;
 
public class UI {
 
  public static void main(String[] args) {
 
  URL url = UI.class.getResource(UI.class.getSimpleName() + IConstants.XWT_EXTENSION_SUFFIX);
    try {
      XWT.open(url);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

Run this Main class, UI opens if you click on button, it call the bean EventHandler :

Xwt-event-handler.png

Using Spring with XWT - Spring DI

At this step, we have seen how declare CLR Class as bean Spring. It's not very interesting compare to use CLR class with x:Class. Spring is very powerfull and it give you Dependency Injection capability. In this section we will use Spring Dependency Injection to use a sevice into teh CLR.

At this step we change the label button when user click on it :

public class EventHandler {
 
  protected void clickButton(Event event) {
    Button button = (Button) event.widget;
    button.setText("Hello, world!");
  }
}

In real application CLR class use generally service. Here we will call an HelloService to get the message "Hello, world!". You can find the sample explained here into the bundle eclipse.e4.xwt.springframework.sample2.


Define HelloService

Create an interface ui.IHelloService like this :

package services;
 
public interface IHelloService {
 
	String hello();
 
}

Create the IHelloService implementation like this :

package services.impl;
 
import services.IHelloService;
 
public class HelloService implements IHelloService {
 
	public String hello() {
		return "Hello, world!";
	}
}

Use HelloService into CLR

Modify EventHandler like this to consume the IHelloService :

package ui;
 
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Event;
 
import services.IHelloService;
 
public class EventHandler {
 
  private IHelloService helloService;
 
  public void setHelloService(IHelloService helloService) {
    this.helloService = helloService;
  }
 
  protected void clickButton(Event event) {
    Button button = (Button) event.widget;
    button.setText(helloService.hello());
  }
}

The service will be filled with Spring Depency Injection.

Declare and use bean service

Declare into the ui-context.xml file the helloService :

  <bean name="myService" class="services.impl.HelloService" >
  </bean>

Here prototype is not setted, it's a singleton. Use Dependency Injection to set the service to the CLR class like this :

  <bean name="myUI" class="ui.EventHandler" scope="prototype">
  	<property name="helloService" ref="myService" />
  </bean>

Here the ui-context.xml modified :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
 
  <bean name="myUI" class="ui.EventHandler" scope="prototype">
  	<property name="helloService" ref="myService" />
  </bean>
 
  <bean name="myService" class="services.impl.HelloService" >
  </bean>
 
</beans>

You can launch the UI test to check that IHelloService is consummed by clicking on button.

Using Spring Dynamic Module (OSGi) with XWT

Bundle services

See the org.eclipse.e4.xwt.springframework.osgi.services bundle.

TODO

Advanced features

ICLRFactoryAware

See tests.

If you wish get args or CLRFactory instance frm the CLR class, your CLR class can implements ICLRFactoryAware :

package org.eclipse.e4.xwt.springframework;
 
import org.eclipse.e4.xwt.ICLRFactory;
 
public interface ICLRFactoryAware {
 
  void setCLRFactory(ICLRFactory factory, IArguments args);
}

Where IArguments is the args parsed :

package org.eclipse.e4.xwt.springframework;
 
import org.eclipse.e4.xwt.ICLRFactory;
 
public interface IArguments {
 
	// Default separator
	String DEFAULT_NAME_SEPARATOR = " ";
	String DEFAULT_VALUE_SEPARATOR = "=";
 
	/**
	 * Returns the original source coming from
	 * {@link ICLRFactory#createCLR(String)} which was used to build this
	 * arguments.
	 * 
	 * @return
	 */
	String getSource();
 
	/**
	 * Returns the value of the args name.
	 * 
	 * @param name
	 * @return
	 */
	String get(String name);
}

Example :

public class CLR implements ICLRFactoryAware {
 
	private ICLRFactory factory;
 
	private IArguments args;
 
	public void setCLRFactory(ICLRFactory factory, IArguments args) {
		this.factory = factory;
		this.args = args;
	}

If you have

x:ClassFactory="org.eclipse.e4.xwt.tests.clrfactory.CLRFactory bean=myCLR"

args.getSource() will return "bean=myCLR".

args.get("bean") willl return "myCLR"

XWT.setCLRFactory

Configuration

  • configure if XWT.setCLRFactory(SpringCLRFactory.INSTANCE) is called into teh Activator (if Thread problem is resolved ).
  • configure timeout to track the ApplicationContext

With JVM parameters

With fragments

Fragment linked to org.eclipse.e4.xwt.springframework which contaisn springclrfactory.properties into src folder. Ex :

org.eclipse.e4.xwt.springclrfactory.timeout = 4000
org.eclipse.e4.xwt.springclrfactory.bundle = org.eclipse.e4.xwt.springframework.osgi.sample1

You can find fragment sample which configure SpringCLRFactory into the org.eclipse.e4.xwt.springframework.config.springclrfactory fragment .

Debug

You can debug the org.eclipse.e4.xwt.springframework bundle with standard OSGi Trace.

Back to the top