Saturday November 25, 2006 Acegi Tutorial in deutsch; Login Abfrage via AJAX
Ein paar interessante Links zum ACEGI Security Framework und AJAX Login Abfragen:
AJAX Security im allgemeinen:
Es scheint, dass nicht nur ich, sondern auch immer mehr andere Leute versuchen,
die Wikipedia Funktionalität in Java nachzubauen
JAMWiki ist in diesem Bereich das neueste und meiner Meinung nach vielversprechendste Projekt für einen Wikipedia Clone in Java:
Aber auch in diesem Projekt von Mingli Juan wird ein eingener Wiki Renderer in Java entwickelt:
Posted by axelclk ( Aug 19 2006, 11:34:09 PM CEST ) Permalink Comments [0]
Ein einfaches Beispiel für eine mit dem GWT erstellte Matrixeingabeform. Bei einem vergrößern oder verkleinern der Matrix wird immer die Methode createMatrix() aufgerufen. Diese Methode könnte man wahrscheinlich noch optimieren, um die bei einem resizing der Matrix einmal vorbesetzten Werte nicht wieder zu löschen.
Das Coding ist auf das GWT KitchenSink Beispiel angepasst:
package org.matheclipse.gwt.client;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
/**
* Creates a resizable Matrix input
* @author Axel Kramer ( axelclk_gmail_com )
*/
public class Matrix extends Sink {
public static SinkInfo init() {
return new SinkInfo("Matrix", "Input the data of your matrix.") {
public Sink createInstance() {
return new Matrix();
}
};
}
private TextBox fRowsTextBox = new TextBox();
private TextBox fColumnsTextBox = new TextBox();
private HorizontalPanel fMatrixPanel = new HorizontalPanel();
private TextBox[][] fTextBoxArray;
private int fRows = 10;
private int fColumns = 12;
private Grid fMatrixGrid;
private TextBox fValue = new TextBox();
private final Button fDimButton = new Button("Set matrix dimensions");
private final Button fSetValueButton = new Button("Set cell value");
public Matrix() {
fDimButton.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
try {
int rows = Integer.parseInt(fRowsTextBox.getText());
int columns = Integer.parseInt(fColumnsTextBox.getText());
if (fRows > 0 && fRows <= 20 && fColumns > 0
&& fColumns <= 20) {
fRows = rows;
fColumns = columns;
createMatrix(fRows, fColumns);
}
} catch (NumberFormatException e) {
}
}
});
fSetValueButton.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
for (int i = 0; i < fRows; i++) {
for (int j = 0; j < fColumns; j++) {
fTextBoxArray[i][j].setText(fValue.getText());
}
}
}
});
fRowsTextBox.setText(Integer.toString(fRows));
fColumnsTextBox.setText(Integer.toString(fColumns));
HorizontalPanel dimensionPanel = new HorizontalPanel();
dimensionPanel.setSpacing(4);
dimensionPanel.add(new Label("Rows:"));
dimensionPanel.add(fRowsTextBox);
dimensionPanel.add(new Label("Columns:"));
dimensionPanel.add(fColumnsTextBox);
dimensionPanel.add(fDimButton);
HorizontalPanel valuePanel = new HorizontalPanel();
valuePanel.add(new Label("Cell value:"));
valuePanel.add(fValue);
valuePanel.add(fSetValueButton);
VerticalPanel verticalPanel = new VerticalPanel();
verticalPanel.setSpacing(8);
verticalPanel.add(dimensionPanel);
verticalPanel.add(valuePanel);
verticalPanel.add(fMatrixPanel);
createMatrix(fRows, fColumns);
setWidget(verticalPanel);
}
private void createMatrix(int rows, int columns) {
// clear old matrix widgets
fMatrixPanel.clear();
TextBox widget;
fTextBoxArray = new TextBox[rows][columns];
fMatrixGrid = new Grid(rows, columns);
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < columns; ++j) {
widget = new TextBox();
widget.setVisibleLength(5);
fMatrixGrid.setWidget(i, j, widget);
fTextBoxArray[i][j] = widget;
}
}
fMatrixGrid.setWidth("100%");
fMatrixGrid.setBorderWidth(1);
fMatrixGrid.setCellSpacing(1);
fMatrixPanel.add(fMatrixGrid);
}
}
Posted by axelclk
( Aug 03 2006, 06:37:56 PM CEST )
Permalink
Comments [0]
Wie wird eine Google Web Toolkit Anwendung im Browser geladen?
Es folgt ein grober Ãberblick, wie die MathEclipse GWT Anwendung im Browser geladen wird.
Die Details kann man in den *cache.html Dateien analysieren, wenn der Compiler mit der Option -style pretty gestartet wurde.
Calc.html wird geladen
gwt.js JavaScript Datei geladen
gwt.js JavaScript Datei arbeitet Meta Tags in der Calc.html ab,
gwt-module Meta Tag content='org.matheclipse.gwt.Calc', wird vom gwt.js ein neuer IFRAME im Browser erzeugt und in diesen IFRAME wird die org.matheclipse.gwt.Calc.nocache.html Datei geladen.
org.matheclipse.gwt.Calc.nocache.html Datei enthält JavaScript Code um zu erkennen, von welchem Browser (mögliche Browser: ie6, moz, oldmoz, opera, und safari) aus die Seite aufgerufen wurde. Nachdem der Browser erkannt wurde, ersetzt sich die Seite selber durch eine Browser spezifische HTML Datei (eine der Dateien mit dem Namen .............cache.html)
gwt.js die gwtOnLoad() Methode im IFRAME auf und die MathEclipse Anwendung wird gestartet.
Genial wäre auch, wenn man aus den erzeugten Dateien wieder eine allgemeine JavaScript Komponente (wie z.B. einen AutoComplete Editor) "extrahieren" könnte, die unabhängig vom GWT Rahmenwerk funktioniert. Dies scheint mir aber trotz der -style pretty Option aus dem generierten Sourcecode heraus und auch unter Berücksichtigung, dass es für alle unterstützten Browser funktionieren sollte, sehr schwierig zu sein.
GWT Applikation entwickeln und deployen in Tomcat
Für die Projekte MathEclipse.org (Online AJAX Calculator) und JTidy.de (HTML to Wiki Converter) habe ich jetzt eine Version auf den Server gestellt, die auf dem Google Web Toolkit basiert.
Das Coding des MathEclipse Projekts findet man im CVS Modul org.matheclipse.gwt.
Nachfolgend habe ich einige Punkte aufgeschrieben, die mir beim Entwickeln und Deployen besonders aufgefallen sind.
| Contents |
|---|
In der org.matheclipse.gwt/calc.gwt.xml Datei wird der Servlet Pfad /me definiert:
<module> <-- <Inherit the core Web Toolkit stuff. --> <inherits name='com.google.gwt.user.User'/> <-- <Specify the app entry point class. --> <entry-point class='org.matheclipse.gwt.client.Calc'/> <servlet path='/me' class='org.matheclipse.gwt.server.CalcServiceImpl'/> </module>
org.matheclipse.gwt.client beginnen, werden vom GWT zum Erzeugen von client-seitigem JavaScript Code verwendet.
org.matheclipse.gwt.server abgelegt werden.
In einer GWT Anwendung benutzt man den RPC Mechanismus um Daten vom Server nachzuladen (im erzeugten JavaScript Code wird dabei, wie sonst auch bei AJAX Anwendungen üblich, ein XMLHttpRequest abgesetzt).
Um einen RPC zu erstellen muss man 2 Java Interfaces und eine Klasse definieren.
Zuerst einmal ein Java Interface für den Evaluierungs Service. Dieses Interface muss das GWT RemoteService Interface erweitern.
package org.matheclipse.gwt.client;
import com.google.gwt.user.client.rpc.RemoteService;
public interface CalcService extends RemoteService {
public String evaluate(String expression, String function, int counter);
}
Das zweite Interface für den Client wird benutzt um die Service Methode asynchron aufzurufen.
package org.matheclipse.gwt.client;
import com.google.gwt.user.client.rpc.AsyncCallback;
interface CalcServiceAsync {
public void evaluate(String expression, String function, int counter, AsyncCallback callback);
}
GWT benutzt dabei ein Callback Interface AsyncCallback, dass die Antwort des Servers für unsere Anwendung "aufbereitet". Als Namenskonventiion verlangt GWT, dass das Kürzel "Async"
an den Namen des Service Interfaces CalcService angehängt wird.
Diese 2 Interfaces sind Teil des Java Codes, der benutzt wird, um den JavaScript Code zu erzeugen.
Als letzten Schritt implementieren wir eine Servletklasse, die das CalcService Interface implementiert. Diese Klasse muss RemoteServiceServlet erweitern, die wiederum eine von der Standard Java Klasse HttpServlet abgeleitete Klasse ist. Die Servlet Klasse muss später mit auf den Tomcat Webserver deployed werden.
package org.matheclipse.gwt.server;
...
...
public class CalcServiceImpl extends RemoteServiceServlet implements
CalcService {
public String evaluate(String expression, String function, int counter) {
...
...
}
...
...
}
In der Eclipse Entwicklungsumgebung kann man das Programm Calc-compile.cmd starten.
Dadurch wird im Unterordner /org.matheclipse.gwt/www/org.matheclipse.gwt.Calc aus den Java Dateien der entprechende komprimierte JavaScript Code erzeugt.
Die ersten Versionen meiner Anwendung hatten im Firefox 1.5 einen Fehler (unter IE6.0 im GWT "hosted mode" funktionierte die Anwendung hingegen tadellos). Dabei wurde eine nichtssagende Fehlermeldung herausgegeben:
uncaught exception: com.google.gwt.core.client.JavaScriptException: JavaScript TypeError exception: seb has no properties
Als erste Massnahme um das Problem einzukreisen hatte ich mir deshalb Firebug installiert. Mit dem Feature Spy on XMLHttpRequest traffic konnte man zumindest erkennen, dass das Problem nicht auf dem Server liegt, weil kein XMLHttpRequest mehr abgesetzt wurde.
(dies Ergebnis war auch zu erwarten, weil die Anwendung ja unter IE6 funktionierte
)
Als nächsten Schritt habe ich dann in dem Calc-compile.cmd Skript die Option
-style pretty gesetzt, damit der GWT Compiler den JavaScript Code in lesbarer Form erzeugt.
Jetzt konnte man im Firebug Debugger erkennen, dass in der Funktion _$__evaluate ein Call zum serialisieren des RPC requests _$writeObject(_stream, _function) den Fehler erzeugte.
In der Variablen _function stand dabei der Wert "eval".
Ich vermute mal das Firefox mit der Serialisierung nicht klarkommt, da "eval" unter JavaScript ein Schlüsselwort ist? Nach der Umbenennung der Funktion von "eval" nach "$eval" funktionierte das Ganze dann auch unter Firefox.
Der Fehler lässt sich im übrigen mit einem Firefox 1.5 immer noch reproduzieren, wenn man in der MathEclipse Textarea nur das Wort "eval" eingibt und dann den Button Symbolic Eval drückt.
Die MathEclipse Anwendung hat diese neuen Features aufgrund der Verwendung des GWT bekommen:
Das Web-Application Verzeichnis lautet tomcat/webapps/me
Alle benötigten *.jar Dateien der Webanwendung müssen wie üblich in das tomcat/webapps/me/WEB-INF/lib Verzeichnis kopiert werden.
Aus der von Google mitgelieferten gwt-user.jar müssen alle javax.* Klassen entfernt werden, da diese mit den vom Tomcat verwendeten javax.* Klassen kollidieren (dies habe ich einfach mit einem ZIP Tool gemacht). Nachtrag: ab GWT Version 1.1.0 wird die Datei gwt-servlet.jar mitgeliefert, so dass man jetzt die javax.* Klassen nicht mehr entfernen muss.
Alle Dateien die unterhalb von /org.matheclipse.gwt/www/org.matheclipse.gwt.Calc liegen, per FTP auf den Tomcatserver in das tomcat/webapps/me Verzeichnis kopieren.
Probleme können durch die verschiedenen URL Kontexte in denen GWT jeweils benutzt wird entstehen. Wenn die Anwendung in Tomcat deployed wurde liefert GWT.isScript() den Wert true zurück im hosted mode hingegen den Wert false:
ServiceDefTarget target = (ServiceDefTarget) service;
if (GWT.isScript()) {
String url = GWT.getModuleBaseURL();
url += "/me";
target.setServiceEntryPoint(url);
} else {
target.setServiceEntryPoint("/me");
}
In der webapps/me/WEB-INF/web.xml stehen die folgenden Angaben:
<servlet> <servlet-name>CalcServiceImpl</servlet-name> <servlet-class>org.matheclipse.gwt.server.CalcServiceImpl</servlet-class> <load-on-startup/> </servlet> <servlet-mapping> <servlet-name>CalcServiceImpl</servlet-name> <url-pattern>/me</url-pattern> </servlet-mapping>Posted by axelclk ( Jul 26 2006, 06:11:35 PM CEST ) Permalink Comments [1]
Das MathEclipse Plugin ist jetzt einfacher erweiterbar durch "provider extensions". Der Kern beinhaltet nur noch die Verwaltung des Editors, der Preferences und der Views. Die eigentlichen Funktionalitäten zur Evaluierung und für das Plotten von Funktionen sind jetzt in 2 eigene Plugins ausgelagert:
Als Beispiel habe ich mir in der Entwicklungsumgebung ein Mathematica Plugin integriert, dass einen Ausdruck über die J/Link Schnittstelle in einem Mathematica Kernel ausführt.
GWT Eclipse Start-Tutorial von Ed Burnette
Der Blog Eintrag von Ed Burnette zeigt, wie man es macht:
Ich hatte es vorher nie geschafft vernünftig in den Debug Modus umzuschalten
Auch ganz nett:
JBlogEditor mit Roller Weblogger Plugins Erweiterung
Der Autor des Eclipse RCP JBlogEditor Programms, Lokesh Shah, hat mir freundlicherweise den Quelltext seines Blog Editors zur Verfügung gestellt.
Inzwischen habe ich den Editor (und die Roller Weblogger XMLRPC Schnittstelle) so erweitert, dass man die im Bliki.info Blog aktiven Plugineinstellungen in den Editor herunterladen und beim Posten des Blogs auch wieder hochladen kann.
Die server-unabhängigen Plugins habe ich mit in den Editor eingebaut, so dass sie den HTML Text der Vorschau entsprechend mit rendern.
So sieht die derzeitige Arbeitsversion des Editors im Bearbeiten Modus aus:

So sieht der Editor im Vorschau Modus aus:

Links:
Posted by axelclk ( May 27 2006, 12:59:14 PM CEST ) Permalink Comments [0]Den MathEclipse Ausdrucksparser habe ich jetzt ähnlich wie in [1] beschrieben, in einen Parser umgeschrieben, der durch eine Operatortabelle [2] gesteuert wird.
Als weiteres Feature ist geplant, dass der Parser 2 Syntax Varianten unterstützen soll:
Notation im Mathematica Stil:
Parser p = new Parser();
ASTNode obj = p.parseExpression("(#^3)&[x][y,z].{a,b,c}");
assertEquals(obj.toString(), "Dot[Function[Power[Slot[1], 3]][x][y, z], List[a, b, c]]");
Notation im üblichen Stil:
Parser p = new Parser(true);
Object obj = p.parseExpression("Integrate(Sin(x)^2+3*x^4, x)");
assertEquals(obj.toString(), "Integrate[Plus[Power[Sin[x], 2], Times[3, Power[x, 4]]], x]");
Was sonst noch fehlt:
Links:
Google Web Toolkit mit Eclipse getestet
Ich hab heute mal das neue Google Web Toolkit mit Eclipse zusammen ausprobiert.
Es scheint wirklich relativ simpel zu sein eine AJAX Anwendung mit ein paar UI Widgets zu erstellen.
Allerdings war mein Beispiel RPC auch noch recht einfach gestrickt
Auf der Roller Support Seite hat Dave Johnson jetzt die von Wordpress ins Roller System portierten Themen Ocadia und Almost Spring veröffentlicht:
Ajax-friendly JSP components (java.net Artikel)
Auf Java.net stellt Michael Jouravlev sein JSPControls.net Projekt vor.
Unter anderem gibt es Beispiele für eine "Aggregated Ajax Login Komponente", "Tab Control" und einen "Mini Blogger", die sowohl im AJAX Modus (wenn das XMLHTTPRequest Objekt verfügbar ist), als auch im "nicht AJAX" Modus funktionieren sollten:

MathEclipse Scripting Engine (JSR 223)
Für das MathEclipse Projekt [1] habe ich eine zu JSR 223 kompatible Scripting Engine [2] erstellt. Diese Scripting Engine basiert auf dem Java Scripting Framework, das ab Java Version 6.0 im JDK mit enthalten ist.
Das folgende Snippet berechnet z.B. die Ableitung von Sin[x]:
public static void main(String[] args) {
ScriptEngineManager scriptManager = new ScriptEngineManager();
String stringResult = null;
ScriptEngine meEngine = scriptManager.getEngineByExtension("m");
try {
stringResult = (String) meEngine.eval("D[Sin[x],x]");
System.out.println(stringResult);
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
Variablen können aus Java heraus mit Werten "vorbelegt" werden:
try {
meEngine.put("x", new Boolean(true));
meEngine.put("y", new Boolean(true));
stringResult = (String) meEngine.eval("x && y");
// prints True
System.out.println(stringResult);
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
Durch die java.io.Reader Unterstützung in der ScriptEngine#eval() Methode, kann ein Script auch sehr einfach aus einer Datei heraus geladen und ausgeführt werden.
Die folgende Matrix-Multiplikation zeigt einige Möglichkeiten der Parameterübergabe an die ScriptEngine
try {
ArrayList row = new ArrayList();
row.add("List"); // head of the expression
row.add(Integer.valueOf(1));
row.add(Integer.valueOf(2));
row.add(Integer.valueOf(3));
int[] intArr = { 3, 4, 11 };
meEngine.put("x", row);
meEngine.put("y", intArr);
// the test.m file contains this script:
// $m={x, y, {13, 7, 8}};
// $m.$m
ScriptContext context = meEngine.getContext();
context.setAttribute(MathScriptEngine.RETURN_OBJECT, Boolean.TRUE,
ScriptContext.ENGINE_SCOPE);
Object objectResult = meEngine.eval(new
FileReader("C:\\eclipse\\workspace\\org.matheclipse.script\\test.m"));
// print result for this matrix multiplication
// {{1,2,3}, {3, 4, 11}, {13, 7, 8}}.{{1,2,3}, {3, 4, 11}, {13, 7, 8}}
System.out.println(objectResult.toString());
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
Java und C# Quelltexte zur schnellen Berechnung der Fakultät einer positiven ganzen Zahl findet man auf Peter Luschnys Seite:
Posted by axelclk ( May 02 2006, 08:05:04 PM CEST ) Permalink Comments [0]
Auf der Suche nach einem Blogeditor bin ich auf JBlogEditor gestoÃen und habe diesen Eintrag offline in dem Editor geschrieben.
Der Editor ist deswegen so interessant, weil man sich als
Eclipse Anwender beim Schreiben kaum umgewöhnen muss. Nach dem Eintippen einer Anfangssequenz eines HTML-Starttags
wie z.B. <bl und Drücken der Strg+SPACE Tastenkombination, kann der Editor, wie in einem Eclipse HTML-Editor üblich, das HTML Tag automatisch zu <blockquote>...</blockquote> ergänzen
Zur Kommunikation mit dem Blog wird die XML-RPC Schnittstelle (MetaWeblogAPI) benutzt. Als Hostpath für bliki.info
muss zum Beispiel http://www.bliki.info/roller/xmlrpc, der Benutzername und das Passwort für
den Blog eingegeben werden.