Skip to main content

Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Remote Application Platform (RAP) » Nice way to get a lazy loaded, session scoped model (MVC)(Domain models created by Spring consumed by RAP)
Nice way to get a lazy loaded, session scoped model (MVC) [message #1373767] Thu, 22 May 2014 10:06
Thorsten Hilker is currently offline Thorsten HilkerFriend
Messages: 31
Registered: March 2014

We had the problem to produce lazy loaded, session scoped domain models.
Our models are produced by Spring in OSGi bundles.

I want to share our solution.

Here an example model:

package com.imilia.test.model;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.imilia.test.domain.ModelObject;
import com.imilia.test.domain.Person;
import com.imilia.test.interfaces.model.IPersonModel;

public class PersonModel extends ModelObject implements IPersonModel {
	private Person person;
	private IPersonService personService;
	public void add() {
		firePropertyChange("person", this.person, this.person = personService.newPerson());
	public void delete() {
		Person nextPerson = personService.nextPerson(person);
		firePropertyChange("person", this.person, this.person = nextPerson);
	public void load(int oid) {
		firePropertyChange("person", this.person, this.person = personService.getPerson(oid));
	public Person getPerson() {
		return person;
	public void next() {
		firePropertyChange("person", this.person, this.person = personService.nextPerson(person));
	public void previous() {
		firePropertyChange("person", this.person, this.person = personService.previousPerson(person));
	public void save() {


As you can see the scope is "prototype", because Spring is not able to produce "session" scoped beans in OSGi. (Better said it's not that easy to produce "session" scoped beans in OSGi. Or is there an easy way?)

Ok, that was the model. Here is the serviceinterface and the service:

package com.imilia.test.interfaces.model;

import java.util.Arrays;
import java.util.List;

public interface IModelService {
	public static final String PERSONMODEL_MAINPART = "PersonModel_MainPart";
	public static final String PERSONMODEL_MAINPART2 = "PersonModel_MainPart2";
	public static final List<String> models = Arrays.asList(PERSONMODEL_MAINPART,PERSONMODEL_MAINPART2);
	Object getModel(String modelname);


package com.imilia.test.model;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

import com.imilia.test.interfaces.model.IModelService;

public class ModelService implements ApplicationContextAware, IModelService {
	static final private Map<String,String> modelMap = new HashMap<String,String>();

	private ApplicationContext applicationContext = null;
	static {
		modelMap.put(IModelService.PERSONMODEL_MAINPART, "personModel");
		modelMap.put(IModelService.PERSONMODEL_MAINPART2, "personModel");
	public Object getModel(String modelname) {
		return applicationContext.getBean(modelMap.get(modelname));
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		this.applicationContext = applicationContext;

The interesting part here is the map. It allows you to produce different models of the same type. I will come back to this soon.

Here are the spring config files from /META-INF/spring:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""
	<context:component-scan base-package="com.imilia.test.model" />


Nothing special. Just Java-based configuration via annotations (as you can in the 2 classes above (@Component, @Service, ...))

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""

	<osgi:reference id="personService" interface="" />

	<osgi:service ref="modelService" interface="com.imilia.test.interfaces.model.IModelService"/>

personService is the service which accesses the database. It comes from another bundle.

More important is the export of the modelService here.

Ok, that was the "model-bundle".

Now RAP.
I discovered the beautiful mechanism of addons in RAP.
So this is the core idea, a addon which registers the models:

package com.imilia.test.gui;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

import org.eclipse.e4.core.contexts.ContextFunction;
import org.eclipse.e4.core.contexts.IEclipseContext;

import com.imilia.test.interfaces.model.IModelService;

public class DomainModelServiceAddon {

	IModelService modelService;

	public void init(IEclipseContext context) {
		for (String modelname : IModelService.models) {
			context.set(modelname, new ModelContextFunction());

	private class ModelContextFunction extends ContextFunction {
		private Object model;

		public Object compute(IEclipseContext context, String contextKey) {
			if (model == null) {
				model = modelService.getModel(contextKey);

			return model;

Easy code, but mighty (in my opinion Smile)

(It's really astonishing how easy it is to get the modelService from the OSGi-context!)

The idea is to register a factory(ModelContextFunction) in the rap-context instead of the model itself. So you got this lazy loading effect. (Our application will use hundreds of models. Would be a waste of resources and time to load them all at the beginning of a session.
The second idea is trivial: "Get the model if it's empty and store it. Use the stored one, if it's not empty." So you got "session-scope".

OK, but what is the sense?
Here is a part of a view:
	@Inject @Named(IModelService.PERSONMODEL_MAINPART) private IPersonModel personModel;
	private Label lblOid;
	private Label lblVorname;
	private Label lblNachname;
	private Button btnSpeichern;

	public void init(Composite parent) {

		parent.setLayout(new FormLayout());

Now you can see how mighty RAPs DI-context is.
Just one line of code in the view and the domain-model is there.
(Lazy loaded, session scoped)

Now the use of the map in the service becomes clearer.
1. With @Named(IModelService.PERSONMODEL_MAINPART) a model of type "PersonModel" is loaded. If you use the same command in another view. The same model is loaded. (The same session scoped instance).
2. With @Named(IModelService.PERSONMODEL_MAINPART2) a model of type "PersonModel" is loaded. But another instance.

Hope that was a little bit helpful for you.
Comments are welcomed.



[Updated on: Thu, 22 May 2014 19:43]

Report message to a moderator

Previous Topic:Restart application with no cid
Next Topic:Focus lost event with hyperlink in Browser
Goto Forum:

Current Time: Wed Feb 26 05:06:15 GMT 2020

Powered by FUDForum. Page generated in 0.02414 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top