CleverGWT*

From PlcWiki

Jump to: navigation, search

Contents

Installation Steps

  • Repository: ssh://user@oko.clever.cz/home/git/CleverGWT/
  • Path: /java/CleverGWT
  • Entry-point descriptor ...gwt.xml:
 <inherits name="cz.clever.gwt.ext.Module" />
  • Don't forget to check your current version of the GWT

Resources

Resources are located in folder src/cz/clever/gwt/ext/public.

Example of icon usage:

 logoutBtn.setIcon(Resource.Util.getIconPath("door_out")); //$NON-NLS-1$

Unified look of the Clever System applications

Create Project

Select: Google/Web Application Project. Package: cz.clever.nazevaplikace.gwt. GWT 2.4.0

Java Build Path

Projects - CleverGWT

Libraries - CleverGWT/lib/smartgwt-skins.jar, CleverGWT/lib/smartgwt.jar, CleverGWT/lib/log4j.jar

AppEntryPoint

AppEntryPoint is an implementation of the EntryPoint interface.

Invent the application name getAppName () and the implementation:

 public void drawContent(String initData, DataCallback<com.smartgwt.client.widgets.Canvas> callback) { callback.execute(new Canvas()); }
 public void logout() {
	CallbackStatus status = null;
	ServiceCallback<Void> callback = new ServiceCallback<Void>(status, "Logout process") {
		@Override
		public void onSuccesss(Void result) {
			Window.Location.reload();
		}
	};
	Service.Util.get().logout(callback);
 }

Interface Service a ServiceAsync

 @RemoteServiceRelativePath("service")
 public interface Service extends RemoteService, ServiceCore { }

Server side - ServiceImpl

 public class ServiceImpl extends SecuredServiceServlet implements Service {
 
	@Override
	protected String getAppName() {
		return "myAppName";// security role-name
	}
 
	@Override
	protected KeyValueString getUserName() {
		return new KeyValueString() {
 
			@Override
			public String getKey() {return "user-data-key";} 
 
			@Override
			public String getValue() {return (String)getUserData(); /* Default:String */} 
 
			@Override
			public void setValue(String value) {}
 
		};
	}
 }

web.xml

 <servlet>
    <servlet-name>serviceServlet</servlet-name>
    <servlet-class>cz.clever.myapp.gwt.server.ServiceImpl</servlet-class>
  </servlet>
 
  <servlet-mapping>
    <servlet-name>serviceServlet</servlet-name>
    <url-pattern>/myapp/service</url-pattern>
  </servlet-mapping>

myapp.gwt.xml

Add correct DOCTYPE and Other module inherits:

 <inherits name="com.google.gwt.i18n.I18N" />
 <inherits name="com.google.gwt.xml.XML" />
 <inherits name="com.google.gwt.http.HTTP" />
 <inherits name="com.smartgwt.SmartGwt" />
 <inherits name="cz.clever.gwt.ext.Module" />

log4j.properties

.Copy to src

Splash - landing page to your app

Known bug: if this page is not dynamic (jsp), the server sends 304 (not modified) authentication and this causes Firefox to not load the page.

The following html page is added:

 <meta http-equiv="content-type" content="text/html; charset=UTF-8">
 <META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">
 <META NAME="AUTHOR" CONTENT="CLEVER Soft s.r.o.">
 <META name="gwt:property" content="locale=en">
 <body style="background-color: #445566">
 <div style="border: 1px solid #7FBA00; position: absolute; left: 45%; top: 40%; padding: 2px; z-index: 20001; height: auto;">
    <div style="background: white; font: bold 16px tahoma, arial, helvetica; padding: 10px; margin: 0; height: 34px; color: #444;">
    <img src="myapp/images/loading32.gif" width="32" height="32" style="margin-right:8px; float:left; vertical-align:top;"/>
    clever system<br/><span style="font: normal 10px tahoma, arial, helvetica;">My App Title</span>
 </div></div>

app.json

web.xml:

 <context-param>
	<param-name>appname_</param-name>
	<param-value><![CDATA[App Name]]></param-value>
 </context-param>
 <servlet>
  	<servlet-name>appInfo</servlet-name>
  	<servlet-class>cz.clever.gwt.ext.server.AppInfoServlet</servlet-class>
  </servlet>
 
  <servlet-mapping>
    <servlet-name>appInfo</servlet-name>
    <url-pattern>/app.json</url-pattern>
  </servlet-mapping>

Security - web.xml

 <security-constraint>
		<web-resource-collection>
			<web-resource-name>WebResName</web-resource-name>
			<description></description>
			<url-pattern>/*</url-pattern>
			<http-method>GET</http-method>
			<http-method>POST</http-method>
		</web-resource-collection>
		<auth-constraint>
			<role-name>MyApp</role-name>
		</auth-constraint>
	</security-constraint>
 
	<security-constraint>
  		<web-resource-collection>
    		<web-resource-name>Public</web-resource-name>
    		<url-pattern>/app.json</url-pattern>
  		</web-resource-collection>
	</security-constraint>
 
	<login-config>
		<auth-method>FORM</auth-method>
		<form-login-config>
			<form-login-page>/Login.html</form-login-page>
			<form-error-page>/Login.html?failed</form-error-page>
		</form-login-config>
	</login-config>
 
	<security-role>
		<role-name>MyApp</role-name>
	</security-role>

Sounds and pictures

Sounds and icons. Images and icons are in CleverGWT/src/cz/clever/gwt/ext/public/images.

Resources are available only after executionGoogle/GWT Compile.

Example of how to play audio (necessary audio tag in html):

 public static native void playAudio(String audioTagId, double volume) /*-{
		$doc.getElementById(audioTagId).volume = volume;
		$doc.getElementById(audioTagId).play();
 }-*/;

Example of an html tag in the landing page (sounds are not physically part of the application where they are listed, but CleverGWT):

 <audio id="select" autobuffer="autobuffer" preload="auto"> 
 <source src="myapp/sound/select.ogg" type="audio/ogg">
 <source src="myapp/sound/select.mp3" type="audio/mpeg">
 </audio>

ClvListGrid - Extension of ListGrid

Simplification of CRUD usage:

ListGrid grid = new ClvListGrid(new ClvListGrid.Delegate() {
 
			@Override
			public void executeUpdate(ClvListGridResponse response) {
				// Map<String, Object> reqMap = response.getRequestMap();
				// response.response(...
			}
 
			@Override
			public void executeRemove(ClvListGridResponse response) {}
 
			@Override
			public void executeFetch(ClvListGridResponse response) {}
 
			@Override
			public void executeAdd(ClvListGridResponse response) {}
 
			@Override
			public DataSourceField[] createFields() {
				return new DataSourceField[] { new DataSourceTextField("Field Name") };
			}
		});

Note: If you are implementing executeRemove/Add/Fetch you must call response.response(...). Not in executeUpdate.

Real-time data synchronization (only works with URL parameter "im"):

 grid = new ClvListGrid(delegate, "MySubscribeId");

SecuredServiceServlet

Benefits:

  • Request without GWT permutation header will be blocked (potential CSRF attack)
  • Authorization check before the servlet methods are called from client (methods must be annotated as Secured)
 public class MyGWTServiceImpl extends SecuredServiceServlet implements ...
 
 @Override
 protected boolean isInRole(String user, String method, Object value, Integer position) {
		// check for permission
 }

JettyLauncher

Allow you to set custom logging and configuration.

Example of startup arguments:

-startupUrl Entrypoint.html ... -server cz.clever.gwt.ext.server.JettyLauncher  ...

Inside a class:

 wac.setConfigurationClasses(new String[] { 
        "org.mortbay.jetty.webapp.WebInfConfiguration", 
        "org.mortbay.jetty.plus.webapp.EnvConfiguration",//jetty-env 
        "org.mortbay.jetty.plus.webapp.Configuration", //web.xml 
        "org.mortbay.jetty.webapp.JettyWebXmlConfiguration",//jettyWeb 
 });

DocumentServlet and UploadServlet

HttpServlet solution for uploading and downloading documents.

Example of upload servlet configuration:

 <servlet>
		<servlet-name>MaterialUpload</servlet-name>
		<servlet-class>cz.clever.cct.gwt.app.server.MyUploadServlet</servlet-class>
		<init-param>
	        <param-name>repository</param-name>
			<param-value>/tmp</param-value>
        </init-param>
        <init-param>
	        <param-name>maxMemSize</param-name>
			<param-value>2147483646</param-value>
        </init-param>
        <init-param>
	        <param-name>maxFileSize</param-name>
			<param-value>2147483646</param-value>
        </init-param>
	</servlet>

StringUtil

java.util.StringTokenizer is prohibited in the GWT client side. Here is my substitution:

 StringUtil.tokenizer("Jirka, Petr, Honza", ",", new ValueCallback() {
 
	@Override
	public void execute(String token) {
		// Your code
	}
 });

Way how to build a delimiter separated string from collection:

 ToString<MaterialOption> toStr = new ToString<MaterialOption>() {
 
	@Override
	public String get(MaterialOption obj) { //make a token from object
		return obj.toString();
		// or if you want: return obj == null? null:obj.getOptionString();
	}
 };
 // collection with filling of course
 Collection<MaterialOption> myCollection = new ArrayList<MaterialOption>();
 
 String result = StringUtil.toString(myCollection, ", ", toStr);

ParserCSV

 new ParserCSV(new ParserCSV.Delegate() {
 
			@Override
			public void token(String token, int position) {
				// working with parsed tokens
			}
 
			@Override
			public String getPath() { return "MyTable.csv"; }
 
			@Override
			public String getDelimeter() { return ";";}
 
			@Override
			public String getCharsetName() { return "UTF-16"; }
 });

BCrypt

String hashed = BCrypt.hashpw("password", BCrypt.gensalt());
boolean verified = BCrypt.checkpw("password", hashed);

String Externalizer (i18n)

Ant external task declaration example:

 <target name="externalizer">
		<taskdef name="externalizer" classname="cz.clever.gwt.ext.ant.Externalizer"/>
		<externalizer 
			        substitution="ClientConst.Util.get().%label()" 
			        labelMaxLength="20"
			        labelPrefix="lbl"
					fileConst="src/cz/clever/cct/gwt/app/client/ClientConst.java">
 
			        <fileset dir="src/cz/clever/cct/gwt/app/client">
			            <include name="*.java" />
			        	<exclude name="ClientConst.java"/>
			        </fileset>
			</externalizer>
	</target>

ClientConst.java (com.google.gwt.i18n.client.Constants) output example:

 @DefaultStringValue("Devices")
 String lblDEVICES();
Personal tools