Skip navigation
Toggle Sidebar

giu_module

GIU (Grid Interface Unit)

This module is a great innovation in terms of using the space. The objective is use the space as a remote , fault-tolerant high scalable user interface provider. In that way , the application user interface is not deployed inside the web container but obtained via openspaces operations.

Deploying user interface inside the gigaspace can give great advantages

  • Easy of deployment : deployment is just a matter of write the UI using any scripting or templating techonology , test it along the grid and deploy inside the GIU PU
  • Manutenability : If the UI needs some correction or improvement , the programmer can alter the template and redeploy it to the space without redeployment of all the client application.
  • Scalability : if the client application demands high user interaction (like CRM or portals), the administrator only adds more nodes to grid and automatically the GIU PU is up and running !
  • Fault Tolerance : in future releases , some UI versionning support can be added easily so there is no service disruption in case of changing templates or partial site failure

Class Diagram

Fig 1 shows the main classes of GIU module shows the main classes of GIU module

Sequence Diagram


Some interesting informations

  • ScreenTemplates have both "View" and "Model" : this makes sense because the intent of some user interface is expose data from some model .
  • The client application never access the ScreenTemplate : the ScreenTemplate can be implemented with many java templating frameworks (actually just groovy is supported). All dependencies stay centralized inside the space and the client application only have dependency to the GIU PU common.jar artifact.
  • Use of JSon : the protocol for exchanging data between the Screen and the ScreenTemplate and between Screen and the world is JSon . This facilitates integration between heterogeneous frameworks

Example

For GoDo, there is a simple example of ScreenTemplate groovy based implementation.

package org.openspaces.godo.giu.pojo;

import java.io.*
import groovy.xml.MarkupBuilder
import java.lang.reflect.Modifier as Modifier
import java.lang.reflect.Field as Field


class Screen1 extends ScreenTemplate {

  def StringWriter render(boolean readOnly, Object structure) {
    def writer = new StringWriter()
    def html = new groovy.xml.MarkupBuilder(writer)
        html.html {
            head {
                title 'Constructed by MarkupBuilder'
            }
            body  (onLoad:'javascript:fillData("' + getId() + '");') {
                h1 'What can I do with MarkupBuilder?'
                def count = 1;
                form (action:'whatever' , name:'main') {
                    table {

                       structure.getClass().getDeclaredFields().each() { field ->
                       if (Modifier.isPrivate(field.'modifiers')) {
                       def hidden = field.getName().startsWith("_");
                       if (hidden) {
                          input(type:'hidden',id:field.getName(), name:field.getName(), value:structure.getProperty(field.getName()))
                       }
                       tr {
                           if (!hidden) {
                               td { label(for:field.getName(), field.getName()) }
                           }
                           td {
                           if (field.getType().isAssignableFrom(Boolean.class)&& !hidden) {
                              structure.getProperty(field.getName())?input(type:'checkbox',checked:'checked',id:field.getName(), ''):input(type:'checkbox',id:field.getName(), '')
                           } else if (field.getType().isAssignableFrom(String.class)|| field.getType().isAssignableFrom(Double.class)) {
                                 input(type:'text',id:field.getName(), value:structure.getProperty(field.getName()))
                           }
                           }
                           count++
                           }
                        }
                        } // isPrivate
                    } //table
                    if (!readOnly) {
                    input(type:'button' , onClick:'javascript:save("' + getId() + '");', value:'Save')
                    }
                }
            }
        }
     return writer
  }
  def void setProperty(String key, Object value, Object host) {
      host.setProperty(key,value)
  }

  def Object createModel() {
      return new QuantityModel()
  }

  def Object clone() {
      Screen1 s = new Screen1();
      return s;
  }

  def String getId() {
  	  return "SCR_1";
  }
  def List<String> getProperties() {
  	def list = new ArrayList<String>();
	Field[] arr = createModel().getClass().getDeclaredFields();
	for(int i = 0 ; i < arr.length ; i++) {
		Field f = arr[i];
		if (Modifier.isPrivate(f.getModifiers())) {
			f.setAccessible(true);
			list.add(f.getName());
		}
	}
	return list
  }
  def Object getProperty(String name, Object host) {
  	return host.getProperty(name)
  }

}

  class QuantityModel {
     private Double quantity = 1.1;
     private Boolean _isDonor = false
  }

def s = new Screen1()
return s

In Red we can see two important fragments

  • save :this is a predefined javascript generic function. When the users press 'Save' all html components have their content sent to the server;
  • createModel : this method is the model used to read and write information to this screen;

Well, to use this template , is very easy too:

ScreenService service = ServiceFactory().getScreenService();
Screen template = new Screen();
template.setScreenService(service);
template.setId(interest.getScreenId());
template.fillEmptyData();
String html = service.render(template,false);

 The above fragment (extracted from GWT-Client/org.openspaces.godo.server.GodoAccessServiceImpl.java) simply renders the html. See that we pass only the ID from screen. But , what occurs when the user press 'Save' ?

Screen screen = new Screen();
screen.setScreenService(ServiceFactory().getScreenService());
screen.setId(id);
try {
	screen.fillData(new DataProvider() {
		public String getValue(String fieldName) {
			Object o = data.get(fieldName);
			if (o != null) {
			// Asks for the conversion field
				return o.toString();
			} else {
				return null;
			}
		}

		public void setValue(String key, Object value) {
			String correspondentField = (String) interest.getInterestParameters().get(key);
			if (correspondentField != null) {
				interestAccount.getInterestParameters().add(correspondentField
						, value);
			}
		}
	});
} catch (IllegalArgumentException e) {
	throw new SavingException("Error saving data because you passed a wrong value " + e.getMessage());
}

Here finally we can see how to pass data to the Screen. First of all, we can see that the Screen object accepts instances of DataProvider as method argument of "fillData" . In this case, we implement the method getValue reading values from some Map object and passing it as String to the Screen. The Screen knows the model of some ScreenTemplate as we've seen before so it can validates and convert to the correct data types. When the conversion goes fine, the method setValue is automatically called.

In this case , the setValue implementation repasses the objects to the object that consumes data produced by the execution of some ScreenTemplate . Here we've got the data chain : many can read or write information !
 

Adaptavist Theme Builder Powered by Atlassian Confluence