CleverGWT*
From PlcWiki
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();