Search
Calendar
September 2017
S M T W T F S
« Sep    
 12
3456789
10111213141516
17181920212223
24252627282930
Your widget title
Archives

Posts Tagged ‘GWT’

PostHeaderIcon Useful DTD

DTDs are useful when your XML editor take them in account: detecting errors, suggestions, complete statements… For instance, I save much time with IntelliJ IDEA automatic completion ; unlike, Eclipse amazingly does not implement this feature.

Here is a list of some widely used DTDs:

File DTD
weblogic-application.xml
<!DOCTYPE weblogic-application PUBLIC "-//BEA Systems, Inc.//DTD WebLogic Application 7.0.0//EN" "http://www.oracle.com/technology/weblogic/weblogic-application/1.1/weblogic-application.xsd">
weblogic-application.xml
<!DOCTYPE weblogic-application PUBLIC "-//BEA Systems, Inc.//DTD WebLogic Application 7.0.0//EN" "http://www.oracle.com/technology/weblogic/weblogic-application/1.1/weblogic-application.xsd">
web.xml
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >
*.hbm.xml
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
GWT modules
<!DOCTYPE module SYSTEM "http://google-web-toolkit.googlecode.com/svn/trunk/distro-source/core/src/gwt-module.dtd">
GWT UI
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
Tangosol / Oracle Coherence
<!DOCTYPE coherence SYSTEM "coherence.dtd">
Log4J
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

Tangosol and Log4J DTDs are included within their distribution JARs: you have to extract them or to give their path to IntelliJ IDEA.

PostHeaderIcon GWT / Sonar / Cannot invoke clone() on the array type… / The user-supplied array … is stored directly

I have to fix all critical “Violations” owing to Sonar.
Let’s consider a basic block:

	public void setSushis(float[] sushis) {
		this.sushis = sushis;
	}

This piece of code raises this error in Sonar:

 Security - Array is stored directly : The user-supplied array 'sushis' is stored directly.

In a naive step, I modified the code as this:

	public void setSushis(float[] sushis) {
		this.sushis = sushis.clone();
	}

This may have been OK… but, now, I get the following error within GWT compilation:

Cannot invoke clone() on the array type float[]

To fix the issue, I amended the code as follows:

	public void setSushis(float[] theSushis) {
        this.sushis= new float[theSushis.length];
        System.arraycopy(theSushis, 0, this.sushis, 0, theSushis.length);
	}

Disclaimer: even though I followed Sonar’s advice and requirements, I am a little skeptic about this kind of “violation”. 😐

PostHeaderIcon Tutorial: an Event Bus Handler for GWT / GXT

Overview

Introduction

Let’s consider a application, JonathanGwtApplication, divided in three main panels

  • a panel to select animal name name
  • a panel to display, expand and collapse trees of the animal ancestors
  • a panel of information to display many indicators (colors, ages, etc.).

An issue we encounter is: how to make the different panels communicate? In more technical terms, how to fire events from a panel to another one?

A first solution would be to declare each panel as listener to the other panels. Indeed, this principle may go further, and declare each component as listener to a list of other components…
Main drawbacks:

  • the code becomes hard to read
  • adding or removing a component requires to modify many parts of the code
  • we don’t follow GWT 2’s “philosophy”, which is to use Handlers rather than Listeners.

Hence, these reasons incited us to provide a global EventBusHandler.

The EventBusHandler concept

The EventBusHandler is a global bus which is aware of all events that should be shared between different panels, and fires them to the right components.
The EventBusHandler is a field of JonathanGwtApplicationContext.

Intrastructure

  • lalou.jonathan.application.web.gwt.animal.events.HandledEvent: generic interface for a event. Abstract method:
    EventTypeEnum getEventEnum();
  • lalou.jonathan.application.web.gwt.animal.handler.EventHandler: generic interface for a component able to handle an event. Abstract method:
    void handleEvent(HandledEvent handledEvent);
  • lalou.jonathan.application.web.gwt.animal.handler.EventHandlerBus: the actual bus. As a concrete class, it has two methods:
    /**
    	 * Fires an event to all components declared as listening to this event
    	 * event type.
    	 *
    	 * @param baseEvent
    	 */
    	public void fireEvent(HandledEvent baseEvent) {
                   // ...
    	}
    
    	/**
    	 * Adds an listener/handler for the event type given as parameter
    	 *
    	 * @param eventTypeEnum
    	 * @param eventHandler
    	 * @return The List of handlers for the key given as parameter. This list
    	 *         contains the eventHandler that was given as second parameter
    	 */
    	public List<EventHandler> put(EventTypeEnum eventTypeEnum,
    			EventHandler eventHandler) {
                  // ...
            }

How to use the bus?

  1. Define an event: in JonathanGwtApplication, an event is decribed by two elements:
    • a functionnal entity: eg: “animal”, “food”, “tree node”. The functionnal entity must be isomorph to a technical DTO, eg: AnimalDTO for an entity Animal.(in the scope of this turoriel we assume to have DTOs, even though the entities may ne sufficient)
    • a technical description of the event: “selection changed”, “is expanded”
  2. Add an entry in the enum EventTypeEnum. Eg: “ANIMAL_SELECTION_CHANGED
  3. in lalou.jonathan.application.web.gwt.animal.events, create an event, implementing HandledEvent and its method getEventEnum(). The match between EventTypeEnum and DTO is achieved here. Eg:
    public class AnimalSelectionChangedEvent extends
    		SelectionChangedEvent<AnimalDTO> implements HandledEvent {
    
    	public AnimalSelectionChangedEvent(
    			SelectionProvider<AnimalDTO> provider,
    			List<AnimalDTO> selection) {
    		super(provider, selection);
    	}
    
    	public EventTypeEnum getEventEnum() {
    		return EventTypeEnum.ANIMAL_SELECTION_CHANGED;
    	}
    
    }
  • When an event that should interest other component is fired, simply call the bus. The bus will identify the event type and dispatch it to the relevant handlers. eg:
    animalComboBox.addSelectionChangedListener(new SelectionChangedListener<AnimalDTO>() {
    
    			@Override
    			public void selectionChanged(SelectionChangedEvent<AnimalDTO> se) {
    				final AnimalDTO selectedAnimalVersion;
    				selectedAnimalVersion= se.getSelectedItem();
    				JonathanGwtApplicationContext.setSelectedAnimal(selectedAnimal);
    
    						final AnimalSelectionChangedEvent baseEvent = new AnimalSelectionChangedEvent(
    								se.getSelectionProvider(), se.getSelection());
    						JonathanGwtApplicationContext.getEventHandlerBus()
    								.fireEvent(baseEvent);
    
    			}
    		});
  • Handlers:
    • easy case: the component handles only one type of event: this handler must implement the right interface (eg: AnimalSelectionChangedEventHandler) and its method, eg:
      protected void handleAnimalSelectionChangedEvent(HandledEvent handledEvent) {
          return;
      }
    • frequent case: the component handles two or more event types. No matter, make the component implement all the needed interfaces (eg: AnimalSelectionChangedEventHandler, FoodSelectionChangedEventHandler). Provide a unique entry point for the method to implement, which is common to both interfaces. Retrieve the event type, and handle it with ad hoc methods. Eg:
      public void handleEvent(HandledEvent handledEvent) {
      		final EventTypeEnum eventTypeEnum;
      
      		eventTypeEnum = handledEvent.getEventEnum();
      
      		switch (eventTypeEnum) {
      		case ANIMAL_SELECTION_CHANGED:
      			handleAnimalSelectionChangedEvent(handledEvent);
      			return;
      		case FOOD_SELECTION_CHANGED:
      			handleFoodSelectionChangedEvent(handledEvent);
      			return;
      		default:
      			break;
      		}
      	}
      
      	protected void handleAnimalSelectionChangedEvent(HandledEvent handledEvent) {
      		// do something
              }
      	protected void handleFoodSelectionChangedEvent(HandledEvent handledEvent) {
      		// do something else
              }
  • PostHeaderIcon Dynamic serviceUrl with Spring’s HttpInvokerProxyFactoryBean

    Abstract

    How to set dynamically the URL used by a HttpInvokerProxyFactoryBean in a Spring-deployed WAR?

    Detailed Case

    I have to deploy a GWT/GXT application, calling two distant services:
    a remote EJB
    a service accessed through Spring Remoting

    Here is the Spring configuration file I firstly used:

      <util:properties id="jndiProperties" location="classpath:jndi.properties"/>
    	<jee:remote-slsb id="myRemoteEJBService" jndi-name="ejb.remote.myRemoteService"
    		business-interface="lalou.jonathan.myRemoteEJBService"
    		environment-ref="jndiProperties" cache-home="false"
    		lookup-home-on-startup="false" refresh-home-on-connect-failure="true" />
    
    	<bean id="mySpringRemoteService"
    		class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
    		<property name="serviceInterface"
    			value="lalou.jonathan.services.mySpringRemoteService" />
    		<property name="serviceUrl" value="${spring.remote.service.url}"/>
    	</bean>
    

    Unhappily, even though the remote EJB is retrieved (which proves that the jndi file is available in the classpath and rightly loaded), the Spring Remote service is not. I had to write the URL in hard in the configuration file… This is not very efficient when you work in a large team, with different production and testings environments!

    This is the log when myRemoteEJBService bean is loaded:

    2010-08-17 16:05:42,937 DEBUG support.DefaultListableBeanFactory  - Creating shared instance of singleton bean 'myRemoteEJBService'
    2010-08-17 16:05:42,937 DEBUG support.DefaultListableBeanFactory  - Creating instance of bean 'myRemoteEJBService'
    2010-08-17 16:05:42,937 DEBUG support.DefaultListableBeanFactory  - Eagerly caching bean 'myRemoteEJBService' to allow for resolving potential circular references
    2010-08-17 16:05:42,937 DEBUG support.DefaultListableBeanFactory  - Returning cached instance of singleton bean 'jndiProperties'
    2010-08-17 16:05:42,937 DEBUG support.DefaultListableBeanFactory  - Invoking afterPropertiesSet() on bean with name 'myRemoteEJBService'
    2010-08-17 16:05:42,937 DEBUG framework.JdkDynamicAopProxy        - Creating JDK dynamic proxy: target source is EmptyTargetSource: no target class, static
    2010-08-17 16:05:42,953 DEBUG support.DefaultListableBeanFactory  - Finished creating instance of bean 'myRemoteEJBService'

    That is the log when mySpringRemoteService is loaded:

    2010-08-17 16:05:42,968 DEBUG support.DefaultListableBeanFactory  - Creating shared instance of singleton bean 'mySpringRemoteService'
    2010-08-17 16:05:42,968 DEBUG support.DefaultListableBeanFactory  - Creating instance of bean 'mySpringRemoteService'
    2010-08-17 16:05:42,984 DEBUG support.DefaultListableBeanFactory  - Eagerly caching bean 'mySpringRemoteService' to allow for resolving potential circular references
    2010-08-17 16:05:43,234 DEBUG support.DefaultListableBeanFactory  - Invoking afterPropertiesSet() on bean with name 'mySpringRemoteService'
    2010-08-17 16:05:43,250 DEBUG framework.JdkDynamicAopProxy        - Creating JDK dynamic proxy: target source is EmptyTargetSource: no target class, static
    2010-08-17 16:05:43,250 DEBUG support.DefaultListableBeanFactory  - Finished creating instance of bean 'mySpringRemoteService'

    You can notice that no mention to jndiProperties appears. Here is the key of the problem: jndiProperties is considered as a bean among others, which cannot be accessed easyly from the HttpInvokerProxyFactoryBean.

    Fix

    To fix the issue, you have to add an actual property holder in Spring XML configuration file, ie after:

    <util:properties id="jndiProperties" location="classpath:jndi.properties"/>

    add an instanciation of PropertyPlaceholderConfigurer:

    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="location" value="classpath:jndi.properties"/>
        </bean>

    PostHeaderIcon GWT in noserver mode with Tomcat or WebLogic

    Abstract

    You would like to work on the client side of your GWT application, without building and deploying the Jetty server. Or, in the same way, you need test some server features available in WebLogic but not in Jetty, such as the EJB.
    GWT 2.0 documentation, at the segment How do I use my own server in hosted mode instead of GWT’s built-in Jetty instance? is not precise at all on the 3rd step: it simply states:

    “change the URL at the end of the argument list to match the URL you recorded in step #1.”

    Process

    • Let’s assume your WAR is deployed on http://distantMachine:8080/myApplication. The servlet container may be Tomcat or WebLogic, it does not matter
    • In Eclipse, go in “Run Configuration...“. Duplicate your current and classic GWT application configuration.
    • Go in Server , uncheck “Run built-in server“.
    • In Arguments tab, write the following line:
      -noserver -remoteUI "${gwt_remote_ui_server_port}:${unique_id}" -logLevel INFO -war C:\eclipse\workspace\myApplication\src\main\webapp\lalou.jonathan.web.gwt.MyApplication -startupUrl http://distantMachine:8080/myApplication lalou.jonathan.web.gwt.MyApplication
    • Run
    • The application is available at the following address:
      http://distantMachine:8080/muyApplication/?gwt.codesvr=127.0.0.1:9997