<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4412946060994304744</id><updated>2012-02-17T05:12:25.692+01:00</updated><title type='text'>voodoo bits</title><subtitle type='html'>about bits, bytes and the essential voodoo to get by</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://voodoobits.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4412946060994304744/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://voodoobits.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Stefan</name><uri>http://www.blogger.com/profile/09590954467358613683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4412946060994304744.post-4297742324665256548</id><published>2009-07-05T18:35:00.084+02:00</published><updated>2009-08-25T18:13:03.234+02:00</updated><title type='text'>Comparing Database Structures</title><content type='html'>&lt;h3&gt;Overview&lt;/h3&gt;&lt;span style="font-size:small"&gt;(Deutschsprachige Anleitung in &lt;span style="font-style:italic;"&gt;liesmich.txt&lt;/span&gt;)&lt;/span&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Djembe&lt;/span&gt; helps in keeping the structures of several database for development, testing, integration and production synchronized&lt;br /&gt;&lt;li&gt;Database independent due to the usage of JDBC drivers&lt;br /&gt;&lt;li&gt;Compare databases offline&lt;br /&gt;&lt;li&gt;Export results to Excel&lt;br /&gt;&lt;li&gt;Structures are saved as XML, thus allowing any further processing&lt;br /&gt;&lt;li&gt;usable via command line or with its own GUI&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Environment:&lt;ul&gt;&lt;li&gt;Java 6 or newer&lt;br /&gt;&lt;li&gt;JDBC Driver (drivers for Oracle, MS SQL Server, Postgres, MySQL, Derby/JavaDB and Firebird were tested successfully)&lt;br /&gt;&lt;/ul&gt;Verified for Windows XP SP3 and openSUSE 11.&lt;br /&gt;&lt;br&gt;The main two components are:&lt;ul&gt;&lt;li&gt;The scanner analyzes database structures and saves them as xml files.&lt;br /&gt;&lt;li&gt;The comparer reads previously stored xml scans and writes the comparison result  as plain text log files, respectively presenting the result as GUI table.&lt;br /&gt;&lt;/ul&gt;Both components are configured via plain text property files:&lt;ul&gt;&lt;li&gt;file suffix .djs for scanners&lt;br /&gt;&lt;li&gt;file suffix .djc for comparisons&lt;br /&gt;&lt;/ul&gt;Currently, the following database objects are processed:&lt;ul&gt;&lt;li&gt;Tables with columns and privileges&lt;br /&gt;&lt;li&gt;Views with columns and privileges&lt;br /&gt;&lt;li&gt; Columns with type, length, and nullable flag&lt;br /&gt;&lt;li&gt; Sequences/generators with privileges&lt;br /&gt;&lt;li&gt; Oracle synonyms&lt;br /&gt;&lt;li&gt; Trigger (without source code so far)&lt;br /&gt;&lt;li&gt; Primary- and foreign keys&lt;br /&gt;&lt;li&gt; Indexes&lt;br /&gt;&lt;li&gt;Types&lt;br /&gt;&lt;/ul&gt;(Privilege, type, trigger and other vendor specific scanners are not part of the&lt;br /&gt;free standard edition)&lt;br /&gt;  &lt;br /&gt;&lt;h3&gt;Usage&lt;/h3&gt;For installation, just copy the application folder to the desired place and add the required JDBC drivers (to the "lib" folder usually).&lt;br /&gt;Please don't forget to copy your license key "djembe-license.txt" into the root folder of the application.&lt;br /&gt;&lt;pre style="font-family: courier new"&gt;java -jar djembe.jar &lt;br /&gt;-ui | &lt;br /&gt;-scan [scan-properties] | &lt;br /&gt;-compare [compare-properties]&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-family: courier new"&gt;-ui&lt;/span&gt; &lt;br /&gt;Launches the graphical user interface of Djembe.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new"&gt;-scan&lt;/span&gt; &lt;br /&gt;Reads a database and stores its structure as xml file.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new"&gt;-compare&lt;/span&gt; &lt;br /&gt;Compares two databases.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Examples:&lt;/span&gt;&lt;span style="font-family: courier new"&gt;&lt;br /&gt;java -jar djembe.jar -scan scan-my-db.djs&lt;br /&gt;java -jar djembe.jar -compare compare-my-dbs.djc&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Under Windows, you can use "djembe.exe" or "djembe.bat", under linux "djembe.sh" for running the graphical user interface as well.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Privilege markup in scans and comparison results:&lt;br /&gt;[grantor] -&gt; [grantee]: [privilege]&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Column Aliases:&lt;/span&gt;&lt;br /&gt;They allow to look at different data types as synonyms causing no difference alert.&lt;br /&gt;A typical example would be to equalize Oracle's specific "varchar2" and the standard "varchar".&lt;br /&gt;You can set up as many mappings as you like, each one comma separated:&lt;br /&gt;&lt;br /&gt;[mapping-1], [mapping-2], ..., [mapping-n]&lt;br /&gt;&lt;br /&gt;Data types and flags are separated by spaces:&lt;br /&gt;&lt;span style="font-family: courier new"&gt;&lt;br /&gt;[Leading data type] [-is] [-id] [Alias-1] ... [Alias-n]&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Flags:&lt;br /&gt;-id ignore digits&lt;br /&gt;-is ignore size&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;"int4 -id -is number numeric, varchar2 varchar"&lt;br /&gt;&lt;br /&gt;Fields of type "int4" are put together with "number" and "numeric". &lt;br /&gt;Both size and number of digits are ignored.&lt;br /&gt;Additionally, data types "varchar2" and "varchar" are taken as identical.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Useful mappings:&lt;/span&gt;&lt;span style="font-family: courier new"&gt;&lt;br /&gt;varchar2 varchar,&lt;br /&gt;int4 -id -is number numeric,&lt;br /&gt;boolean -id -is char,&lt;br /&gt;date -id -is timestamp,&lt;br /&gt;blob -is bytea,&lt;br /&gt;bpchar char,&lt;br /&gt;numeric number&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Scanner-Properties&lt;/h3&gt;&lt;pre style="font-family: courier new"&gt;url =             (database URL to analyze)&lt;br /&gt;alias =           (short database name, free to choose)&lt;br /&gt;driver =          (JDBC driver class)&lt;br /&gt;driverUrl =       (JDBC driver URL)&lt;br /&gt;user =            (database user, might need administrator rights !)&lt;br /&gt;schema =          (database schema)&lt;br /&gt;filter =          (name filter for tables, views, etc.)&lt;br /&gt;scanner.classes = (comma separated list of scanner classes to run)&lt;br /&gt;replace =         (automatically replaces written xml result file, true oder false)&lt;br /&gt;exportName =      (name pattern of the written xml file)&lt;br /&gt;&lt;/pre&gt;Folder "templates" contains several sample property files for various databases like Oracle, Postgres or MySql.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Comparer-Properties&lt;/h3&gt;&lt;pre style="font-family: courier new"&gt;comparer.log.charset =           (charset of the generated log file)&lt;br /&gt;comparer.ignoreIndexNames =      (ignore index names, true oder false)&lt;br /&gt;comparer.log.name =              (name pattern of the generated log file)&lt;br /&gt;comparer.ignoreForeignKeyNames = (ignore foreign key names, true oder false)&lt;br /&gt;comparer.ignorePrivileges =      (ignore privileges, true oder false)&lt;br /&gt;comparer.ignorePrimaryKeyNames = (ignore primary key names, true oder false)&lt;br /&gt;comparer.ignoreColumnTypes =     (ignore data types, true oder false)&lt;br /&gt;comparer.ignoreSchemas =         (ignore schemas, true oder false)&lt;br /&gt;comparer.database.1 =            (first, previously scanned database as xml)&lt;br /&gt;comparer.database.2 =            (second, previously scanned database as xml)&lt;br /&gt;comparer.log.replace =           (automatically overwrite the generated log file, true oder false)&lt;br /&gt;comparer.column.aliases =        (mappings for column aliases)&lt;br /&gt;comparer.log.separator =         (separator char of the generated log file)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Available Scanner&lt;/h3&gt;&lt;span style="font-family: courier new"&gt;default.TableScanner&lt;br /&gt;default.ViewScanner&lt;br /&gt;royalty.TypeScanner&lt;br /&gt;&lt;br /&gt;oracle.SequenceScanner&lt;br /&gt;oracle.SynonymScanner&lt;br /&gt;oracle.TriggerScanner&lt;br /&gt;&lt;br /&gt;postgres.SequenceScanner&lt;br /&gt;postgres.DomainScanner&lt;br /&gt;postgres.TriggerScanner&lt;br /&gt;&lt;br /&gt;firebird.GeneratorScanner&lt;br /&gt;firebird.TriggerScanner&lt;br /&gt;&lt;br /&gt;mysql.TriggerScanner&lt;br /&gt;&lt;br /&gt;derby.SynonymScanner&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;h3&gt;File Suffixes&lt;/h3&gt;.djs = scanner configuration&lt;br /&gt;.djc = comparison configuration&lt;br /&gt;.djd = database dump&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Get it here:&lt;/h3&gt;&lt;a href="http://www.jroots.de/html/download.html"&gt;Downloads&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Soon to come:&lt;/span&gt;&lt;br /&gt;Professional version with more scanners for privileges, types, triggers and other vendor specific objects.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.voodoosoft.de/djembe/djembe2-small.jpg "&gt;&lt;img style="float:left; margin:0 0 10px 10px;cursor:pointer; cursor:hand" src="http://www.voodoosoft.de/djembe/djembe2-small.jpg " border="0" alt="" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4412946060994304744-4297742324665256548?l=voodoobits.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://voodoobits.blogspot.com/feeds/4297742324665256548/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4412946060994304744&amp;postID=4297742324665256548' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4412946060994304744/posts/default/4297742324665256548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4412946060994304744/posts/default/4297742324665256548'/><link rel='alternate' type='text/html' href='http://voodoobits.blogspot.com/2009/07/comparing-database-structures.html' title='Comparing Database Structures'/><author><name>Stefan</name><uri>http://www.blogger.com/profile/09590954467358613683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4412946060994304744.post-8189002238914923959</id><published>2009-06-02T12:53:00.006+02:00</published><updated>2009-06-02T14:34:13.373+02:00</updated><title type='text'>Neues auf Java basierende Portal freigeschaltet</title><content type='html'>Gestern konnte endlich das neue Künstlerportal &lt;a href="http://www.artist-jobs.de"&gt;Artist Jobs&lt;/a&gt; freigeschaltet werden.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Technologische Basis&lt;/span&gt; ist wie folgt:&lt;br /&gt;- Java 5&lt;br /&gt;- Spring (komplette Konfiguration mittels Dependency Injection, Cron Jobs)&lt;br /&gt;- Hibernate&lt;br /&gt;- Postgres 8.3&lt;br /&gt;- JSF mit den RichFaces (inklusive Ajax)&lt;br /&gt;- YAML (CSS-Unterstützung, Aufteilung der Seiten in verschiedene Bereiche, IE-Hacks)&lt;br /&gt;- iText (Rechnungserstellung)&lt;br /&gt;- JRoots (Dynamische JSF-Tabellen, -Controller und -Security, Hibernate-Wrapper)&lt;br /&gt;- Apache HttpClient (für die Anbindung des externen Zahlungsdienstleisters)&lt;br /&gt;- JWPlayer als Flash-Player&lt;br /&gt;- Log4J&lt;br /&gt;- JUnit&lt;br /&gt;- POI (initialer Import von Strukturdaten aus Excel-Sheets)&lt;br /&gt;- Apache Tomcat als Servlet Container&lt;br /&gt;- Apache HttpServer als Webserver&lt;br /&gt;- Linux mit OpenSuse 10 auf dem Root-Server&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Anforderungen&lt;/span&gt;&lt;br /&gt;- Webseiten sind durchgehend mit relativen Bildschirmbreiten gestaltet&lt;br /&gt;- Jeder Benutzer kann mehrere Seiten des gleichen Typs, aber unterschiedlichen Objekten bzw. Inhalten parallel sichten und pflegen (Stichwort "Page Scope")&lt;br /&gt;- Der Registrierungsprozess für neue Benutzer ist mehrstufig (Versand von Bestätigungsmails)&lt;br /&gt;- Die Zahlungsabwicklung muß selbständig periodisch Mitgliedsbeiträge einziehen können, dabei Rechnungen generieren, versenden und auf abgelehnte Zahlungen reagieren&lt;br /&gt;- Bei Uploads von Dateien muß der Dateityp anhand von "Magic Bytes" überprüft werden&lt;br /&gt;- Versuche, HTML-Tags in Felder einzugeben, muß verhindert werden&lt;br /&gt;- Benutzereingaben werden niemals in SQL-Strings direkt eingebettet, es werden immer Prepared Statements verwendet&lt;br /&gt;- Für zeitkritische Suchanfragen muß händisch optimiertes SQL möglich sein, oder, noch weiterführend, die Umgehung von Hibernate durch Austausch der verwendeten &lt;span style="font-style:italic;"&gt;DataFactory &lt;/span&gt;(einfache Umkonfiguration in Spring-Dateien) &lt;br /&gt;- Einige Daten, die die Benutzer beispielsweise in Drop-Down-Boxen präsentiert bekommen, müssen in mehreren Sprachen vorliegen. Die Spracheinstellung der Benutzer entscheidet, welche Daten herangezogen werden.&lt;br /&gt;- Die Datenbank muß täglich automatisch gesichert werden (über einen Linux-Cron Job und FTP)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Anmerkungen, Probleme, Lösungen&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;File-Uploads&lt;br /&gt;&lt;br /&gt;Aus angedachten 1-2 Stunden wurden mehrere Tage. Es war anfänglich nicht möglich, größere Dateien ohne Abbruch auf den Rootserver zu übertragen. Offenbar ein Problem in der Kommunikation zwischen Webserver und Tomcat. Googlen brachte zwar einige ähnliche Fälle hervor, jedoch keine Lösung. &lt;br /&gt;Die Lösung war dann jedoch simpel: nach dem Wechsel vom Apache Commons FileUpload zur RichFaces fileUpload-Komponente gab es keine Abbrüche mehr - ohne etwas an der Konfiguration zwischen Tomcat und Webserver zu ändern.&lt;br /&gt;Allerdings sollte der Spaß noch nicht vorbei. Was nun mit dem FireFox funktionierte, brachte den Internet Explorer zum Stillstand: nach erfolgtem Upload fror der IE ein und war nur noch mit Gewalt zu beenden. Allerdings offenbar nur mit der Version meines Entwicklungsrechners. Andere Leute mit dem IE6 haben keine Probleme...&lt;br /&gt;&lt;br /&gt;Flash, Ajax, HTML, JavaScript&lt;br /&gt;&lt;br /&gt;Eine zuweilen unseelige Kombination. Es musste nach Auswahl eines Eintrags ein Flashplayer mit neuen dynamischen Inhalten versorgt werden. Ein Albtraum aus JSF, Ajax-Repaints, Hidden Fields und Redirects.&lt;br /&gt;Funktioniert nun nach etlichem Gefrickel aber doch.&lt;br /&gt;Meistens werden die Repaint-Aufforderungen der RichFaces brav befolgt. Manchmal jedoch auch nicht. Auch nach weiterem Probieren nicht. Oder auch längerem Probieren. Dann bleibt nur ein primitiver Redirect, um Seiteninhalte zu aktualisieren.&lt;br /&gt;&lt;br /&gt;Mail-Versand&lt;br /&gt;&lt;br /&gt;Eigentlich eine simple Sache. Spring bietet einen Wrapper für die Java Mail-API. Es war jedoch unmöglich, sich beim Provider zu authentifizieren. Die Mail-API bietet verschiedene Möglichkeiten dafür, von denen letztendlich nur eine (bei direkter Verwendung ohne Spring) erfolgreich war.&lt;br /&gt;&lt;br /&gt;Lasttest&lt;br /&gt;Nach dem ersten Test mit JMeter zeigte sich schnell eine Optimierungsmöglichkeit: Die auf ersten Seite angezeigte Tabelle wird nun nicht mehr ad hoc aus der Datenbank aufgebaut, sondern aus einem Cache angefordert, der initial beim Hochfahren des Servers gefüllt wird, sowie anschließend bei allen mit den Daten verbundenen Speicheraktionen aktualisiert.&lt;br /&gt;Weiterhin werden Objekte für Drop-Down-Boxen vorbereitet: Hier werden nicht die reinen Daten vorgehalten, sondern fertig nutzbare &lt;span style="font-style:italic;"&gt;SelectItem&lt;/span&gt;-Objekte.&lt;br /&gt;Als Drittes werden die Strukturen von dynamisch erzeugten JSF-Tabellen vorgehalten.&lt;br /&gt;&lt;br /&gt;Datenbank-Sessions&lt;br /&gt;&lt;br /&gt;Um Probleme mit &lt;span style="font-style:italic;"&gt;lazy&lt;/span&gt;-geladenen Hibernate-Objekten zu vermeiden, versorgt ein Servlet-Filter jeden Request mit einer gültigen Datenbankverbindung und schließt am Ende des Requests selbige wieder bzw. gibt diese frei.&lt;br /&gt;&lt;br /&gt;Erstellen der Datenbank&lt;br /&gt;&lt;br /&gt;Dazu gehört die Versorgung mit initialen Strukturdaten. Diese liegen in Excel-Sheets vor und werden mittels POI einmalig in die Datenbank übernommen.&lt;br /&gt;&lt;br /&gt;Zahlungsabwicklung&lt;br /&gt;&lt;br /&gt;Zum Einzug von Zahlungen wird über den Apache HttpClient die externe Schnittstelle des Zahlungsdienstleisters aufgerufen. Im Gegenzug lauscht ein Servlet auf Rückmeldungen, die über Erfolg oder Misserfolg berichten und kann dann entsprechend reagieren(z.B. Mails versenden, Benutzer sperren, etc.).&lt;br /&gt;&lt;br /&gt;Cron Jobs&lt;br /&gt;&lt;br /&gt;Sollte es im laufenden Betrieb zu Problemen in der Anbindung externer Dienste (z.B. für Mail oder Zahlungen) kommen, sorgen verschiedene Jobs mit Hilfe von Spring Schedulern dafür, daß zugehörige aufgelaufene Aufgaben dennoch abgearbeitet werden.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4412946060994304744-8189002238914923959?l=voodoobits.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://voodoobits.blogspot.com/feeds/8189002238914923959/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4412946060994304744&amp;postID=8189002238914923959' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4412946060994304744/posts/default/8189002238914923959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4412946060994304744/posts/default/8189002238914923959'/><link rel='alternate' type='text/html' href='http://voodoobits.blogspot.com/2009/06/neues-auf-java-basierende-portal.html' title='Neues auf Java basierende Portal freigeschaltet'/><author><name>Stefan</name><uri>http://www.blogger.com/profile/09590954467358613683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4412946060994304744.post-1832074324394859938</id><published>2009-02-01T17:28:00.009+01:00</published><updated>2009-02-23T17:44:26.834+01:00</updated><title type='text'>Various small how-tos for the JSF beginner</title><content type='html'>&lt;span style="font-weight:bold;"&gt;A - Changing the locale of the current running session&lt;/span&gt;&lt;br&gt;&lt;br /&gt;1. Set up a managed session bean for storing the locale.&lt;br&gt;&lt;br /&gt;2. Intialize the locale from the browser settings:&lt;br /&gt;&lt;pre&gt;public SessionBean() {&lt;br /&gt;   FacesContext context = FacesContext.getCurrentInstance();&lt;br /&gt;   HttpServletRequest request =&lt;br /&gt;      (HttpServletRequest)context.getExternalContext().getRequest();&lt;br /&gt;   sessionLocale = request.getLocale();&lt;br /&gt;&lt;br /&gt;   if (!Locale.GERMAN.equals(sessionLocale) &amp;&amp;&lt;br /&gt;       !Locale.ENGLISH.equals(sessionLocale)) {&lt;br /&gt;      sessionLocale = Locale.ENGLISH;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Make sure to fall back to your default locale in case of unknown locales.&lt;br /&gt;&lt;br&gt;&lt;br /&gt;3. Implement a simple getter and setter for the locale:&lt;br /&gt;&lt;pre&gt;public Locale getLocale() {&lt;br /&gt;   return sessionLocale;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void setLocale(Locale sessionLocale) {&lt;br /&gt;   this.sessionLocale = sessionLocale;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;4. In every JSF page, ask for the current locale:&lt;br /&gt;&lt;pre&gt;&amp;lt;f:view locale="#{sessionBean.locale}"&gt;&lt;/pre&gt;&lt;br /&gt;5. For switching the locale, add flag buttons or a user profile form.&lt;br /&gt;&lt;br /&gt;&lt;br&gt;&lt;span style="font-weight:bold;"&gt;B - Redirect to another place&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;void redirect(String url) {&lt;br /&gt;   FacesContext context = FacesContext.getCurrentInstance();&lt;br /&gt;   HttpServletResponse response = (HttpServletResponse)context.getExternalContext().getResponse();&lt;br /&gt;   String path = context.getExternalContext().getRequestContextPath();&lt;br /&gt;   response.sendRedirect(path + url);&lt;br /&gt;}&lt;/pre&gt;The &lt;span style="font-style:italic;"&gt;url&lt;/span&gt; given does not contain the application's context as prefix&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;C - Get a resource text for the current locale:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;String getResourceText(String key) {&lt;br /&gt;   String text = null;&lt;br /&gt;&lt;br /&gt;   String bundleName = FacesContext.getCurrentInstance().getApplication().getMessageBundle();&lt;br /&gt;   Locale loc = FacesContext.getCurrentInstance().getViewRoot().getLocale();&lt;br /&gt;   ResourceBundle bundle = ResourceBundle.getBundle(bundleName, loc);&lt;br /&gt;&lt;br /&gt;   try {&lt;br /&gt;      text = bundle.getString(key);&lt;br /&gt;   }&lt;br /&gt;   catch (MissingResourceException e) {&lt;br /&gt;      log.error(e);&lt;br /&gt;      text = "! " + key + " !";&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   return text;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;D - Get current session id&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;public String getSessionId() {&lt;br /&gt;   FacesContext context = FacesContext.getCurrentInstance();&lt;br /&gt;   return ((HttpSession)context.getExternalContext().getSession(false)).getId();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;E - Get a request parameter&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;Object param = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("theParam");&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;F - Clear input of text fields and selected drop-down-lists&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;public void clearFields() {&lt;br /&gt;   UIViewRoot uiRoot = FacesContext.getCurrentInstance().getViewRoot();&lt;br /&gt;   recurseChildren(uiRoot);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;protected void recurseChildren(UIComponentBase comp) {&lt;br /&gt;   for (int i = 0; i &lt; comp.getChildren().size(); i++) {&lt;br /&gt;      UIComponentBase child = (UIComponentBase)comp.getChildren().get(i);&lt;br /&gt;      recurseChildren(child);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   if (comp instanceof HtmlInputText || comp instanceof HtmlInputTextarea || comp instanceof HtmlSelectOneMenu) {&lt;br /&gt;      ((UIInput)comp).setValue("");&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;G - Clean up expired sessions&lt;/span&gt;&lt;br /&gt;&lt;br&gt;1. Write a session listener:&lt;br /&gt;&lt;pre&gt;public class CleanupListener implements HttpSessionListener {&lt;br /&gt;   public void sessionCreated(HttpSessionEvent event) {&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void sessionDestroyed(HttpSessionEvent event) { &lt;br /&gt;      // clean up right here ... &lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;2. Register the listener in the web.xml:&lt;pre&gt;&amp;lt;listener&gt;&lt;br /&gt;   &amp;lt;listener-class&gt;&lt;br /&gt;      the.full.package.name.CleanupListener&lt;br /&gt;   &amp;lt;/listener-class&gt;&lt;br /&gt;&amp;lt;/listener&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;H - Fix the character encoding&lt;/span&gt;&lt;br /&gt;If you get wrong page encodings for JSF post requests although you specified the content in every single page, setting up a servlet filter helps. Example to force UTF-8:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {&lt;br /&gt;   response.setCharacterEncoding("UTF-8");&lt;br /&gt;   request.setCharacterEncoding("UTF-8");&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4412946060994304744-1832074324394859938?l=voodoobits.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://voodoobits.blogspot.com/feeds/1832074324394859938/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4412946060994304744&amp;postID=1832074324394859938' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4412946060994304744/posts/default/1832074324394859938'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4412946060994304744/posts/default/1832074324394859938'/><link rel='alternate' type='text/html' href='http://voodoobits.blogspot.com/2009/02/various-small-how-tos-for-jsf-beginner.html' title='Various small how-tos for the JSF beginner'/><author><name>Stefan</name><uri>http://www.blogger.com/profile/09590954467358613683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4412946060994304744.post-8307832977625590587</id><published>2008-04-16T15:32:00.023+02:00</published><updated>2009-08-02T18:56:08.265+02:00</updated><title type='text'>JSF &amp; Security</title><content type='html'>This article introduces a Java module which utilizes phase listeners for securing JSF applications.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Feature list:&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;user, password and role based&lt;br /&gt;&lt;li&gt;interfaces throughout for independence of concrete implementations&lt;br /&gt;&lt;li&gt;easy to integrate into a Spring framework environment&lt;br /&gt;&lt;li&gt;supports password and cookie encoding&lt;br /&gt;&lt;li&gt;login data can be placed in cookies for automatic user logins&lt;br /&gt;&lt;li&gt;a special navigation handler ensures that invalid navigation rules do not open security holes&lt;br /&gt;&lt;li&gt;users may be allowed to login to multiple sessions or not&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Introduction&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The security core is independent of JSF. Thus, it could be used for other view technologies as well as for any view-independent access control. This affects all classes for authentication, authorization, access rules and cryptography.&lt;br /&gt;&lt;br /&gt;How does it work ?&lt;br /&gt;&lt;br /&gt;We have &lt;i&gt;identities&lt;/i&gt;, usually representing application users. Identities are grouped by assigning &lt;i&gt;roles&lt;/i&gt;. Access &lt;i&gt;rules&lt;/i&gt; define which roles&lt;br /&gt;are required to path through to certain views.&lt;br /&gt;The &lt;i&gt;authenticator&lt;/i&gt; is responsible for identifying users, whereas &lt;i&gt;guards&lt;/i&gt; process authorization requests and either approve or refuse them.&lt;br /&gt;&lt;br /&gt;Guards do not know whether access requests represent web sites or anything else. They just follow their given rules to make decisions.&lt;br /&gt;Thus, other implementations of &lt;tt&gt;Guard&lt;/tt&gt; and &lt;tt&gt;Rule&lt;/tt&gt; are possible, for example to secure single UI components.&lt;br /&gt;&lt;br /&gt;The following two classes allow the integration of the security core into JSF:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;tt&gt;SecurityListener&lt;/tt&gt; is a phase listener working in the &lt;tt&gt;RESTORE_VIEW&lt;/tt&gt; phase&lt;br /&gt;&lt;li&gt;the &lt;tt&gt;LoginService&lt;/tt&gt; is responsible for logins, cookies and creating identities respectively user objects&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;For denied requests two cases must be distinguished: &lt;br /&gt;&lt;ol&gt;&lt;li&gt;The user is not logged in. If so, the &lt;tt&gt;loginRequiredNavigation&lt;/tt&gt; of &lt;tt&gt;LoginService&lt;/tt&gt; returns the new navigation.&lt;br /&gt;&lt;li&gt;The user was logged in or can be logged in automatically. Then,&lt;br /&gt;&lt;ul&gt;&lt;li&gt;the &lt;tt&gt;Guard&lt;/tt&gt; delivered the violated rule, its &lt;tt&gt;errorView&lt;/tt&gt; is taken as navigation target&lt;br /&gt;&lt;li&gt;property &lt;tt&gt;defaultErrorNavigation&lt;/tt&gt; of &lt;tt&gt;LoginService&lt;/tt&gt; represents the fallback for rules without error view&lt;/ul&gt;&lt;/ol&gt;&lt;br /&gt;In either case, if no valid target can be obtained or any exception raises, a 403-HTTP error is sent.&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Configuration&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Sample Spring configuration:&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;img src="http://www.jroots.de/blog/jsf-security-config.png"/&gt;&lt;br /&gt;&lt;br /&gt;The default navigation handler of JSF is ignorant of invalid navigation rules. Non-existing rule outcomes result in no navigation at all, meaning that view requests which have just been denied, would pass through nevertheless.&lt;br /&gt;The &lt;tt&gt;AssertingNavigationHandler&lt;/tt&gt; takes care of this problem: an &lt;tt&gt;InvalidNavigationRuleException&lt;/tt&gt; is thrown in case of an unknown or maybe just misspelled navigation directive.&lt;br /&gt;&lt;pre&gt;&amp;lt;navigation-handler&gt;&lt;br /&gt;   de.voodoosoft.jroots.ui.jsf.core.AssertingNavigationHandler&lt;br /&gt;&amp;lt;/navigation-handler&gt;   &lt;br /&gt;&lt;/pre&gt;(faces-config.xml)        &lt;br /&gt;&lt;br /&gt;To be able to configure the &lt;tt&gt;SecurityListener&lt;/tt&gt; as Spring bean, the following listener delegate must be installed:   &lt;br /&gt;&lt;pre&gt;&amp;lt;lifecycle&gt;&lt;br /&gt;   &amp;lt;phase-listener&gt;&lt;br /&gt;      de.voodoosoft.jroots.ui.jsf.core.DelegatingPhaseListenerMulticaster&lt;br /&gt;   &amp;lt;/phase-listener&gt;&lt;br /&gt;&amp;lt;/lifecycle&gt;&lt;br /&gt;&lt;/pre&gt;(faces-config.xml)&lt;br /&gt;&lt;br /&gt;The &lt;tt&gt;DelegatingPhaseListenerMulticaster&lt;/tt&gt; automatically searches Spring's application context for registered phase listeners like this:&lt;br /&gt;&lt;pre&gt;&amp;lt;bean id="securityListener"&lt;br /&gt;   class="de.voodoosoft.jroots.ui.jsf.security.SecurityListener"&gt;&lt;br /&gt;   &amp;lt;property name="loginService" ref ="loginService"&gt;&amp;lt;/property&gt;&lt;br /&gt;   &amp;lt;property name="guard" ref="guard"/&gt;  &lt;br /&gt;   &amp;lt;property name="defaultErrorNavigation" value="login"&gt;&amp;lt;/property&gt;&lt;br /&gt;&amp;lt;/bean&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&lt;b&gt;Download and Example&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The complete package jroots-jsf-security.zip with a full working example (folder /examples/example4) and sample Spring configurations can be downloaded here: &lt;a href="http://www.jroots.com"&gt;JRoots Application Bricks&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4412946060994304744-8307832977625590587?l=voodoobits.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://voodoobits.blogspot.com/feeds/8307832977625590587/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4412946060994304744&amp;postID=8307832977625590587' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4412946060994304744/posts/default/8307832977625590587'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4412946060994304744/posts/default/8307832977625590587'/><link rel='alternate' type='text/html' href='http://voodoobits.blogspot.com/2008/04/securing-jsf-application.html' title='JSF &amp; Security'/><author><name>Stefan</name><uri>http://www.blogger.com/profile/09590954467358613683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4412946060994304744.post-5798713908659840189</id><published>2008-04-04T14:56:00.025+02:00</published><updated>2009-08-02T18:57:00.368+02:00</updated><title type='text'>Dynamic JSF tables</title><content type='html'>Here, I like to present a small open source library allowing to dynamically create JSF tables with Java code instead of using JSP tags.&lt;br /&gt;JSP pages tend to get clumsy and not very easy to get at first sight, so we benefit from smaller files, more dynamic views as well as from the decouplement of pages and underlying bean properties.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Features&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The required table structure (shown columns) can be put together by manual coding or automatically from processing properties of a given Java bean.&lt;br /&gt;Column labels can be retrieved from assigned resource files.&lt;br /&gt;The concrete component classes used are externally configured, for example with Spring, thus leaving the table factory independent of various JSF libraries and making it possible to switch the UI without complex engagement.&lt;br /&gt;Numeric columns get right aligned by default.&lt;br /&gt;&lt;br /&gt;At present there are the following column types:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Standard-Text&lt;/li&gt;&lt;li&gt;Link&lt;/li&gt;&lt;li&gt;Checkbox&lt;/li&gt;&lt;li&gt;Drop-Down (&lt;font style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;select&amp;gt;&lt;/font&gt;-Tag)&lt;/li&gt;&lt;li&gt;Image&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;If these column types are not sufficient, additional individually built columns can be integrated as well.&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold;"&gt;Packages:&lt;/font&gt;&lt;br /&gt;&lt;ul&gt;&lt;li style="font-family: courier new;"&gt;de.voodoosoft.jroots.ui.jsf.factory.table&lt;/li&gt;&lt;li style="font-family: courier new;"&gt;de.voodoosoft.jroots.ui.jsf.factory.table.impl&lt;/li&gt;&lt;/ul&gt;Dependencies:&lt;br /&gt;&lt;ul&gt;&lt;li style="font-family: courier new;"&gt;de.voodoosoft.jroots.ui.jsf.core&lt;/li&gt;&lt;li style="font-family: courier new;"&gt;de.voodoosoft.jroots.core.annotations&lt;/li&gt;&lt;/ul&gt;&lt;font style="font-weight: bold;"&gt;&lt;br /&gt;&lt;font style="font-weight: bold;"&gt;Example&lt;/font&gt;&lt;/font&gt;&lt;font style="font-weight: bold;"&gt; jroots-example1&lt;/font&gt;&lt;br /&gt;(configured with Spring's dependency injection):&lt;br /&gt;&lt;br /&gt;What is left inside the JSP is the raw table without columns but with bindings for both the table component and the presented data.&lt;br /&gt;&lt;pre&gt;&lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;h:dataTable&lt;/span&gt; id=&lt;span style="color:#0000ff"&gt;&amp;quot;customerList&amp;quot;&lt;/span&gt;&lt;br /&gt;   binding=&lt;span style="color:#0000ff"&gt;&amp;quot;#{customerController.dataTable}&amp;quot;&lt;/span&gt;&lt;br /&gt;   value=&lt;span style="color:#0000ff"&gt;&amp;quot;#{customerController.beanData}&amp;quot;&lt;/span&gt;&lt;br /&gt;   var=&lt;span style="color:#0000ff"&gt;&amp;quot;rowBean&amp;quot;&lt;/span&gt;&amp;gt;&lt;br /&gt;&lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;/h:dataTable&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In order to resolve Spring beans placed in JSP pages, the following configuration is required:&lt;br /&gt;&lt;br /&gt;&lt;font&gt;web.xml:&lt;/font&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;listener&amp;gt;&lt;/span&gt;&lt;br /&gt;   &lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;listener-class&amp;gt;&lt;/span&gt;&lt;br /&gt;      com.sun.faces.config.ConfigureListener&lt;br /&gt;   &lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;/listener-class&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;/listener&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;listener&amp;gt;&lt;/span&gt;&lt;br /&gt;   &lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;listener-class&amp;gt;&lt;/span&gt;&lt;br /&gt;      org.springframework.web.context.ContextLoaderListener&lt;br /&gt;   &lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;/listener-class&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;/listener&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;faces-config.xml:&lt;br /&gt;&lt;pre&gt;&lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;variable-resolver&amp;gt;&lt;/span&gt;&lt;br /&gt;   org.springframework.web.jsf.DelegatingVariableResolver&lt;br /&gt;&lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;/variable-resolver&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The UI-controller is defined inside Spring'S application context:&lt;br /&gt;&lt;pre&gt;&lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;bean&lt;/span&gt; id=&lt;span style="color:#0000ff"&gt;&amp;quot;customerController&amp;quot;&lt;/span&gt;&lt;br /&gt;   class=&lt;span style="color:#0000ff"&gt;&amp;quot;de.voodoosoft.jroots.examples.example2.ui.jsf.customer.CustomerController&amp;quot;&lt;/span&gt;&lt;br /&gt;   scope=&lt;span style="color:#0000ff"&gt;&amp;quot;request&amp;quot;&lt;/span&gt;&amp;gt;&lt;br /&gt;   &lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;property&lt;/span&gt; name=&lt;span style="color:#0000ff"&gt;&amp;quot;tableFactory&amp;quot;&lt;/span&gt; ref=&lt;span style="color:#0000ff"&gt;&amp;quot;tableFactory&amp;quot;&lt;/span&gt;/&amp;gt;&lt;br /&gt;&lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Dependency injection is used to assign the used &lt;font face="courier new"&gt;TableFactory&lt;/font&gt; to the controller:&lt;br /&gt;&lt;pre&gt;&lt;span style="color:#7f0055; font-weight:bold"&gt;public class&lt;/span&gt; CustomerController &lt;span style="color:#000000"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#7f0055; font-weight:bold"&gt;public&lt;/span&gt; &lt;span style="color:#7f0055; font-weight:bold"&gt;void&lt;/span&gt; &lt;span style="color:#000000"&gt;setTableFactory&lt;/span&gt;&lt;span style="color:#000000"&gt;(&lt;/span&gt;TableFactory factory&lt;span style="color:#000000"&gt;) {&lt;/span&gt;&lt;br /&gt;        &lt;span style="color:#7f0055; font-weight:bold"&gt;this&lt;/span&gt;&lt;span style="color:#000000"&gt;.&lt;/span&gt;factory &lt;span style="color:#000000"&gt;=&lt;/span&gt; factory&lt;span style="color:#000000"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#000000"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color:#7f0055; font-weight:bold"&gt;private&lt;/span&gt; TableFactory factory&lt;span style="color:#000000"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;When JSF asks for the table component, it gets built by the &lt;font face="courier new"&gt;TableFactory&lt;/font&gt;:&lt;br /&gt;&lt;pre&gt;&lt;span style="color:#7f0055; font-weight:bold"&gt;public class&lt;/span&gt; CustomerController &lt;span style="color:#000000"&gt;{&lt;/span&gt;&lt;br /&gt;   &lt;span style="color:#7f0055; font-weight:bold"&gt;public&lt;/span&gt; UIData &lt;span style="color:#000000"&gt;getDataTable&lt;/span&gt;&lt;span style="color:#000000"&gt;() {&lt;/span&gt;&lt;br /&gt;      &lt;span style="color:#7f0055; font-weight:bold"&gt;if&lt;/span&gt; &lt;span style="color:#000000"&gt;(&lt;/span&gt;dataTable &lt;span style="color:#000000"&gt;==&lt;/span&gt; null&lt;span style="color:#000000"&gt;) {&lt;/span&gt;&lt;br /&gt;         TableDefinition tableDef &lt;span style="color:#000000"&gt;=&lt;/span&gt; factory&lt;span style="color:#000000"&gt;.&lt;/span&gt;&lt;span style="color:#000000"&gt;buildDefinition&lt;/span&gt;&lt;span style="color:#000000"&gt;(&lt;/span&gt;CustomerBean&lt;span style="color:#000000"&gt;.&lt;/span&gt;&lt;span style="color:#7f0055; font-weight:bold"&gt;class&lt;/span&gt;&lt;span style="color:#000000"&gt;);&lt;/span&gt;&lt;br /&gt;         dataTable &lt;span style="color:#000000"&gt;=&lt;/span&gt; factory&lt;span style="color:#000000"&gt;.&lt;/span&gt;&lt;span style="color:#000000"&gt;buildTable&lt;/span&gt;&lt;span style="color:#000000"&gt;(&lt;/span&gt;tableDef&lt;span style="color:#000000"&gt;);&lt;/span&gt;&lt;br /&gt;      &lt;span style="color:#000000"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;      &lt;span style="color:#7f0055; font-weight:bold"&gt;return&lt;/span&gt; dataTable&lt;span style="color:#000000"&gt;;&lt;/span&gt;&lt;br /&gt;   &lt;span style="color:#000000"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The table structure follows the properties of the given bean, in this example &lt;span style="font-style:italic;"&gt;name&lt;/span&gt; and &lt;span style="font-style:italic;"&gt;address&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;span style="color:#7f0055; font-weight:bold"&gt;public class&lt;/span&gt; CustomerBean &lt;span style="color:#000000"&gt;{&lt;/span&gt;&lt;br /&gt;   &lt;span style="color:#7f0055; font-weight:bold"&gt;public&lt;/span&gt; &lt;span style="color:#000000"&gt;CustomerBean&lt;/span&gt;&lt;span style="color:#000000"&gt;(&lt;/span&gt;&lt;span style="color:#7f0055; font-weight:bold"&gt;String&lt;/span&gt; name&lt;span style="color:#000000"&gt;,&lt;/span&gt; &lt;span style="color:#7f0055; font-weight:bold"&gt;String&lt;/span&gt; address&lt;span style="color:#000000"&gt;) {&lt;/span&gt;&lt;br /&gt;      &lt;span style="color:#7f0055; font-weight:bold"&gt;this&lt;/span&gt;&lt;span style="color:#000000"&gt;.&lt;/span&gt;name &lt;span style="color:#000000"&gt;=&lt;/span&gt; name&lt;span style="color:#000000"&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color:#7f0055; font-weight:bold"&gt;this&lt;/span&gt;&lt;span style="color:#000000"&gt;.&lt;/span&gt;address &lt;span style="color:#000000"&gt;=&lt;/span&gt; address&lt;span style="color:#000000"&gt;;&lt;/span&gt;&lt;br /&gt;   &lt;span style="color:#000000"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   &lt;span style="color:#7f0055; font-weight:bold"&gt;private&lt;/span&gt; &lt;span style="color:#7f0055; font-weight:bold"&gt;String&lt;/span&gt; name&lt;span style="color:#000000"&gt;,&lt;/span&gt; address&lt;span style="color:#000000"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;font style="font-weight: bold;"&gt;second example&lt;/font&gt;&lt;font style="font-weight: bold;"&gt; jroots-example2&lt;/font&gt; demonstrates the usage of RichFaces components instead of the reference implementation. All that has to be done is to modify the application context: properties of &lt;font face="courier new"&gt;tableFactory&lt;/font&gt; and &lt;font face="courier new"&gt;columnBuilder&lt;/font&gt; get component classes of RichFaces:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;bean&lt;/span&gt; id=&lt;span style="color:#0000ff"&gt;&amp;quot;tableFactory&amp;quot;&lt;/span&gt;&lt;br /&gt;   class=&lt;span style="color:#0000ff"&gt;&amp;quot;de.voodoosoft.jroots.ui.jsf.factory.table.impl.DefaultTableFactory&amp;quot;&lt;/span&gt;&amp;gt;&lt;br /&gt;   &lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;property&lt;/span&gt; name=&lt;span style="color:#0000ff"&gt;&amp;quot;resourceTag&amp;quot;&lt;/span&gt; value=&lt;span style="color:#0000ff"&gt;&amp;quot;res&amp;quot;&lt;/span&gt;/&amp;gt;&lt;br /&gt;   &lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;property&lt;/span&gt; name=&lt;span style="color:#0000ff"&gt;&amp;quot;rowBeanTag&amp;quot;&lt;/span&gt; value=&lt;span style="color:#0000ff"&gt;&amp;quot;rowBean&amp;quot;&lt;/span&gt;/&amp;gt;&lt;br /&gt;   &lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;property&lt;/span&gt; name=&lt;span style="color:#0000ff"&gt;&amp;quot;uiDataClass&amp;quot;&lt;/span&gt; value=&lt;span style="color:#0000ff"&gt;&amp;quot;org.richfaces.component.html.HtmlDataTable&amp;quot;&lt;/span&gt;/&amp;gt;&lt;br /&gt;   &lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;property&lt;/span&gt; name=&lt;span style="color:#0000ff"&gt;&amp;quot;columnBuilder&amp;quot;&lt;/span&gt;&amp;gt;&lt;br /&gt;      &lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;map&amp;gt;&lt;/span&gt;&lt;br /&gt;         &lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;entry&lt;/span&gt; key=&lt;span style="color:#0000ff"&gt;&amp;quot;de.voodoosoft.jroots.ui.jsf.factory.table.ColumnDefinition&amp;quot;&lt;/span&gt; value-ref=&lt;span style="color:#0000ff"&gt;&amp;quot;defaultColumnBuilder&amp;quot;&lt;/span&gt;/&amp;gt;&lt;br /&gt;      &lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;/map&amp;gt;&lt;/span&gt;&lt;br /&gt;   &lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;/property&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#7f0055; font-weight:bold"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Finally, the &lt;font style="font-weight: bold;"&gt;third example&lt;/font&gt;&lt;font style="font-weight: bold;"&gt; jroots-example3&lt;/font&gt; shows generation of link and drop-down columns. There are annotations for both column types. However, there is no need to use those, you can define any column by manual coding as well:&lt;br /&gt;&lt;pre&gt;&lt;span style="color:#7f0055; font-weight:bold"&gt;public class&lt;/span&gt; Guitar &lt;span style="color:#000000"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   &amp;#64;Link&lt;br /&gt;   &lt;span style="color:#7f0055; font-weight:bold"&gt;private&lt;/span&gt; &lt;span style="color:#7f0055; font-weight:bold"&gt;String&lt;/span&gt; name&lt;span style="color:#000000"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   &amp;#64;&lt;span style="color:#000000"&gt;DropDown&lt;/span&gt;&lt;span style="color:#000000"&gt;(&lt;/span&gt;targetEntity &lt;span style="color:#000000"&gt;=&lt;/span&gt; Wood&lt;span style="color:#000000"&gt;.&lt;/span&gt;&lt;span style="color:#7f0055; font-weight:bold"&gt;class&lt;/span&gt;&lt;span style="color:#000000"&gt;)&lt;/span&gt;&lt;br /&gt;   &lt;span style="color:#7f0055; font-weight:bold"&gt;private&lt;/span&gt; &lt;span style="color:#7f0055; font-weight:bold"&gt;Long&lt;/span&gt; bodyWood&lt;span style="color:#000000"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   &amp;#64;&lt;span style="color:#000000"&gt;DropDown&lt;/span&gt;&lt;span style="color:#000000"&gt;(&lt;/span&gt;targetEntity &lt;span style="color:#000000"&gt;=&lt;/span&gt; Wood&lt;span style="color:#000000"&gt;.&lt;/span&gt;&lt;span style="color:#7f0055; font-weight:bold"&gt;class&lt;/span&gt;&lt;span style="color:#000000"&gt;)&lt;/span&gt;&lt;br /&gt;   &lt;span style="color:#7f0055; font-weight:bold"&gt;private&lt;/span&gt; &lt;span style="color:#7f0055; font-weight:bold"&gt;Long&lt;/span&gt; neckWood&lt;span style="color:#000000"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Links can either be mapped to controller methods (&lt;font face="courier new"&gt;formSubmit&lt;/font&gt; = true) or point to external targets. Link targets are set inside the controller:&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold;"&gt;Internal Link:&lt;/font&gt;&lt;br /&gt;&lt;pre&gt;LinkColumnDefinition linkCol &lt;font style="color: rgb(0, 0, 0);"&gt;=&lt;/font&gt; tableDef&lt;font style="color: rgb(0, 0, 0);"&gt;.&lt;/font&gt;&lt;font style="color: rgb(0, 0, 0);"&gt;getColumn&lt;/font&gt;&lt;font style="color: rgb(0, 0, 0);"&gt;(&lt;/font&gt;&lt;font style="color: rgb(0, 0, 255);"&gt;"name"&lt;/font&gt;&lt;font style="color: rgb(0, 0, 0);"&gt;);&lt;/font&gt;&lt;br /&gt;linkCol&lt;font style="color: rgb(0, 0, 0);"&gt;.&lt;/font&gt;&lt;font style="color: rgb(0, 0, 0);"&gt;setTarget&lt;/font&gt;&lt;font style="color: rgb(0, 0, 0);"&gt;(&lt;/font&gt;&lt;font style="color: rgb(0, 0, 255);"&gt;"#{guitarController.onGuitarClicked}"&lt;/font&gt;&lt;font style="color: rgb(0, 0, 0);"&gt;);&lt;/font&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;font style="font-weight: bold;"&gt;External Link:&lt;/font&gt;&lt;br /&gt;&lt;pre&gt;linkCol &lt;font style="color: rgb(0, 0, 0);"&gt;=&lt;/font&gt; &lt;font style="color: rgb(127, 0, 85); font-weight: bold;"&gt;new&lt;/font&gt; &lt;font style="color: rgb(0, 0, 0);"&gt;LinkColumnDefinition&lt;/font&gt;&lt;font style="color: rgb(0, 0, 0);"&gt;(&lt;/font&gt;&lt;font style="color: rgb(0, 0, 255);"&gt;"google"&lt;/font&gt;&lt;font style="color: rgb(0, 0, 0);"&gt;);&lt;/font&gt;&lt;br /&gt;linkCol&lt;font style="color: rgb(0, 0, 0);"&gt;.&lt;/font&gt;&lt;font style="color: rgb(0, 0, 0);"&gt;setOutput&lt;/font&gt;&lt;font style="color: rgb(0, 0, 0);"&gt;(&lt;/font&gt;&lt;font style="color: rgb(0, 0, 255);"&gt;"google"&lt;/font&gt;&lt;font style="color: rgb(0, 0, 0);"&gt;);&lt;/font&gt;&lt;br /&gt;linkCol&lt;font style="color: rgb(0, 0, 0);"&gt;.&lt;/font&gt;&lt;font style="color: rgb(0, 0, 0);"&gt;setFormSubmit&lt;/font&gt;&lt;font style="color: rgb(0, 0, 0);"&gt;(&lt;/font&gt;false&lt;font style="color: rgb(0, 0, 0);"&gt;);&lt;/font&gt;&lt;br /&gt;linkCol&lt;font style="color: rgb(0, 0, 0);"&gt;.&lt;/font&gt;&lt;font style="color: rgb(0, 0, 0);"&gt;setTarget&lt;/font&gt;&lt;font style="color: rgb(0, 0, 0);"&gt;(&lt;/font&gt;&lt;font style="color: rgb(0, 0, 255);"&gt;"http://www.google.de/search?q=#{guitarController.dataTable.rowData.name}"&lt;/font&gt;&lt;font style="color: rgb(0, 0, 0);"&gt;);&lt;/font&gt;&lt;br /&gt;tableDef&lt;font style="color: rgb(0, 0, 0);"&gt;.&lt;/font&gt;&lt;font style="color: rgb(0, 0, 0);"&gt;addColumn&lt;/font&gt;&lt;font style="color: rgb(0, 0, 0);"&gt;(&lt;/font&gt;linkCol&lt;font style="color: rgb(0, 0, 0);"&gt;);&lt;/font&gt;&lt;br /&gt;&lt;/pre&gt;Here we have the characteristic that controller properties are evaluated and passed as URL parameters. To access the current row bean, &lt;font face="courier new"&gt;getRowData()&lt;/font&gt; of &lt;font face="courier new"&gt;UIData&lt;/font&gt; is invoked in this example.&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold;"&gt;Spring configuration:&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.jroots.com/blog/jsf-tablefactory.png"&gt;&lt;img style="cursor: pointer;" src="http://www.jroots.com/blog/jsf-tablefactory.png" alt="" id="BLOGGER_PHOTO_ID_5185710708642632066" border="0"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold;"&gt;Download:&lt;br /&gt;&lt;br /&gt;&lt;/font&gt;All the involved jar files&lt;br /&gt;&lt;ul&gt;&lt;li&gt;jroots-core.jar&lt;/li&gt;&lt;li&gt;jroots-jsf-core.jar&lt;/li&gt;&lt;li&gt;jroots-jsf-factory.jar&lt;/li&gt;&lt;/ul&gt; and the presented examples are available for download: &lt;a href="http://www.jroots.com"&gt;voodoosoft&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4412946060994304744-5798713908659840189?l=voodoobits.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://voodoobits.blogspot.com/feeds/5798713908659840189/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4412946060994304744&amp;postID=5798713908659840189' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4412946060994304744/posts/default/5798713908659840189'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4412946060994304744/posts/default/5798713908659840189'/><link rel='alternate' type='text/html' href='http://voodoobits.blogspot.com/2008/04/dynamische-jsf-tabellen.html' title='Dynamic JSF tables'/><author><name>Stefan</name><uri>http://www.blogger.com/profile/09590954467358613683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4412946060994304744.post-2008595233542648644</id><published>2008-03-27T15:41:00.004+01:00</published><updated>2008-03-27T16:10:59.795+01:00</updated><title type='text'>Frühlingsgesichter - JSF und Spring</title><content type='html'>Spring-Beans lassen sich leicht in JSF-Seiten verwenden.&lt;br /&gt;&lt;br /&gt;Im folgenden Beispiel soll der &lt;span style="font-family:courier new;"&gt;customerController&lt;/span&gt; nicht als normale &lt;span style="font-style: italic;"&gt;Managed Bean&lt;/span&gt; sondern als Spring-Bean definiert werden:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;h:inputText&lt;/span&gt; value=&lt;span style="color: rgb(0, 0, 255);"&gt;"#{customerController.name}"&lt;/span&gt;/&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;1. spring.jar&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Kopieren in den Ordner &lt;span style="font-family:courier new;"&gt;WEB-INF/lib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2. web.xml&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In der web.xml den Pfad zur Spring-Konfiguration festlegen, beispielsweise:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;web-app&amp;gt;&lt;/span&gt;&lt;br /&gt;   &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;context-param&amp;gt;&lt;/span&gt;&lt;br /&gt;       &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;param-name&amp;gt;&lt;/span&gt;contextConfigLocation&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;/param-name&amp;gt;&lt;/span&gt;&lt;br /&gt;       &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;param-value&amp;gt;&lt;/span&gt;classpath:config/applicationContext.xml&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;/param-value&amp;gt;&lt;/span&gt;&lt;br /&gt;   &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;/context-param&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;listener&amp;gt;&lt;/span&gt;&lt;br /&gt;     &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;listener-class&amp;gt;&lt;/span&gt;&lt;br /&gt;        org.springframework.web.context.ContextLoaderListener&lt;br /&gt;     &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;/listener-class&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;/listener&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  (...)&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;/web-app&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;3. faces-config.xml&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Der &lt;span style="font-family: courier new;"&gt;DelegatingVariableResolver &lt;/span&gt;dient zur Auflösung der in den JSF-Seiten benutzten Beans:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;faces-config&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;application&amp;gt;&lt;/span&gt;&lt;br /&gt;     &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;variable-resolver&amp;gt;&lt;/span&gt;&lt;br /&gt;        org.springframework.web.jsf.DelegatingVariableResolver&lt;br /&gt;     &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;/variable-resolver&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;/application&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  (...)&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;/faces-config&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;       &lt;br /&gt;&lt;span style="font-weight: bold;"&gt;4. Beans für den Application Context&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Die JSF-eigene Definition als Managed Bean entfällt - stattdessen wird eine Spring-Bean konfiguriert:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;beans&lt;/span&gt; (...) &amp;gt;&lt;br /&gt;&lt;br /&gt; (...)&lt;br /&gt;&lt;br /&gt; &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;bean&lt;/span&gt; id=&lt;span style="color: rgb(0, 0, 255);"&gt;"customerController"&lt;/span&gt;&lt;br /&gt;      class=&lt;span style="color: rgb(0, 0, 255);"&gt;"whatever.package.CustomerController"&lt;/span&gt;&lt;br /&gt;      scope=&lt;span style="color: rgb(0, 0, 255);"&gt;"request"&lt;/span&gt;&amp;gt;&lt;br /&gt;  &lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(127, 0, 85); font-weight: bold;"&gt;&amp;lt;/beans&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4412946060994304744-2008595233542648644?l=voodoobits.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://voodoobits.blogspot.com/feeds/2008595233542648644/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4412946060994304744&amp;postID=2008595233542648644' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4412946060994304744/posts/default/2008595233542648644'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4412946060994304744/posts/default/2008595233542648644'/><link rel='alternate' type='text/html' href='http://voodoobits.blogspot.com/2008/03/frhlingsgesichter-jsf-und-spring.html' title='Frühlingsgesichter - JSF und Spring'/><author><name>Stefan</name><uri>http://www.blogger.com/profile/09590954467358613683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4412946060994304744.post-7912774185391629684</id><published>2008-03-22T22:21:00.003+01:00</published><updated>2008-03-22T22:36:52.671+01:00</updated><title type='text'>JSF und die Keksfabrik</title><content type='html'>Eine kurze Übersicht über die Behandlung von Cookies unter Java und JSF:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Erzeugen:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;public void bakeCookie(FacesContext ctx) {&lt;br /&gt;  Cookie cookie = new Cookie("tastyCookie", "mySecretCookieData");&lt;br /&gt;  cookie.setMaxAge(604800); // Haltbarkeit in Sekunden&lt;br /&gt;&lt;br /&gt;  HttpServletResponse response = (HttpServletResponse) ctx.getExternalContext().getResponse();&lt;br /&gt;  response.addCookie(cookie);             &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Die eigentlichen Daten sollten selbstverständlich verschlüsselt sein. Weiterhin sollte man in der Verwendung von Sonderzeichen Vorsicht walten lassen - diese könnten je nach Browser zu eigentümlichen Verhalten führen (richtig, genau &lt;span style="font-style: italic;"&gt;der &lt;/span&gt;Browser).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Auslesen:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;public boolean tasteCookie(FacesContext ctx) {&lt;br /&gt;  Map cookieMap = ctx.getExternalContext().getRequestCookieMap();&lt;br /&gt;  Cookie cookie = (Cookie)cookieMap.get("tastyCookie");&lt;br /&gt;  if (cookie != null &amp;amp;&amp;amp; cookie.getValue().length() &gt; 0) {&lt;br /&gt;     // enjoy cookie&lt;br /&gt;     String val = cookie.getValue();&lt;br /&gt;  }&lt;span style="font-family: Georgia,serif;"&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Entsorgen:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;public void eatCookie(FacesContext ctx) {&lt;br /&gt;  Cookie cookie = new Cookie("tastyCookie");&lt;br /&gt;  cookie.setMaxAge(0);&lt;br /&gt;&lt;br /&gt;  HttpServletResponse response = (HttpServletResponse)ctx.getExternalContext().getResponse();&lt;br /&gt;  response.addCookie(cookie);      &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4412946060994304744-7912774185391629684?l=voodoobits.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://voodoobits.blogspot.com/feeds/7912774185391629684/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4412946060994304744&amp;postID=7912774185391629684' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4412946060994304744/posts/default/7912774185391629684'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4412946060994304744/posts/default/7912774185391629684'/><link rel='alternate' type='text/html' href='http://voodoobits.blogspot.com/2008/03/jsf-und-die-keksfabrik.html' title='JSF und die Keksfabrik'/><author><name>Stefan</name><uri>http://www.blogger.com/profile/09590954467358613683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4412946060994304744.post-732626984210453273</id><published>2008-03-22T20:45:00.009+01:00</published><updated>2008-03-22T22:51:46.801+01:00</updated><title type='text'>JSF und die wesentlichen Bestandteile einer Bohne</title><content type='html'>Benötigt man für jedes Feld einer JSF-Seite wirklich ein weitgehend sinnfreies Getter/Setter-Paar in der zugehörigen Managed-Bean ?&lt;br /&gt;Nein - denn JSF ist konfigurierbar und Java bietet das Reflection-Package...&lt;br /&gt;&lt;br /&gt;In der &lt;span style="font-family:courier new;"&gt;faces.config.xml&lt;/span&gt; kann der zu verwendende &lt;span style="font-family:courier new;"&gt;ELResolver&lt;/span&gt; geändert werden:&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;pre&gt;&amp;lt;application&amp;gt;  &lt;br /&gt;  &amp;lt;el-resolver&amp;gt;&lt;br /&gt;     com.whatever.package.FieldResolver&lt;br /&gt;  &amp;lt;/el-resolver&amp;gt;     &lt;br /&gt;&amp;lt;/application&amp;gt;&lt;/pre&gt;&lt;/span&gt;Die Methoden des EL-Resolvers werden dann analog dem folgenden Beispiel für &lt;span style="font-family:courier new;"&gt;getValue&lt;/span&gt; implementiert.&lt;br /&gt;Zuerst wird weiterhin versucht, einen passenden Getter zu finden. Das ist wichtig, um Sonderfälle, die ohne Getter nicht auskommen, behandeln zu können. Wurde keine Methode gefunden, wird nach einem entsprechenden &lt;span style="font-style: italic;"&gt;Class-Field&lt;/span&gt; gesucht. Nur bei letztendlichem Erfolg wird die Anfrage als bearbeitet markiert (&lt;span style="font-family:courier new;"&gt;context.setPropertyResolved(true)&lt;/span&gt;) - andernfalls werden implizit die übrigen EL-Resolver aufgerufen.&lt;br /&gt;Da dies alles nur Sinn macht, wenn es überhaupt um Objekt-Properties geht, werden nur Ausdrücke mit einem Basis-Objekt bearbeitet (&lt;span style="font-family:courier new;"&gt;base != null&lt;/span&gt;).&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public class FieldResolver extends ELResolver {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    private static final Object[] sNoArgs = new Object[0];&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    private static final Class[] sNoClassArgs = new Class[0];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    public Object getValue(ELContext context, Object base, Object property) throws NullPointerException, PropertyNotFoundException, ELException {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        String name = property.toString();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        if (base != null) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            // 1. try getter&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            try {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                String getterName = "get" + name.substring(0, 1).toUpperCase() + name.substring(1);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                Method getter = base.getClass().getMethod(getterName, sNoClassArgs);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                context.setPropertyResolved(true);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                return getter.invoke(base, sNoArgs);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            catch (NoSuchMethodException ne) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                // no error so far           &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            catch (Exception ex) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;                throw new RuntimeException(ex);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            // 2. direct field access&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            try {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                Field field = getField(base, property);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                if (field != null) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                    context.setPropertyResolved(true);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                    return field.get(base);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            catch (Exception e) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;                String message = "Error accessing property '" + name + "' in bean of type " + base.getClass().getName();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;                throw new PropertyNotFoundException(message, e);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        return null;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    }&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4412946060994304744-732626984210453273?l=voodoobits.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://voodoobits.blogspot.com/feeds/732626984210453273/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4412946060994304744&amp;postID=732626984210453273' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4412946060994304744/posts/default/732626984210453273'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4412946060994304744/posts/default/732626984210453273'/><link rel='alternate' type='text/html' href='http://voodoobits.blogspot.com/2008/03/jsf-und-die-wesentlichen-bestandteile.html' title='JSF und die wesentlichen Bestandteile einer Bohne'/><author><name>Stefan</name><uri>http://www.blogger.com/profile/09590954467358613683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4412946060994304744.post-952983454470042228</id><published>2008-03-22T19:13:00.006+01:00</published><updated>2008-03-22T20:43:12.511+01:00</updated><title type='text'>JSF und die Frage wie es losgeht</title><content type='html'>Wer sich erstmals mit den Java Server Faces befasst und/oder von Struts umsteigt, steht wahrscheinlich vor der Frage, wie und wann man am besten einen UI-Controller bzw. die zugrundeliegende(n) &lt;span style="font-style: italic;"&gt;Managed Beans&lt;/span&gt; initialisiert, sprich, die benötigten Daten lädt. Denn alle darzustellenden Felder werden nur lose an beliebige Beans gebunden. Abgesehen von weiterführenden Themen wie Servlet Filtern oder Phase Listenern gibt es keine vordefinierten Einsprungmethoden.&lt;br /&gt;Eine simple Lösung macht sich die Möglichkeit der Expression Language (EL)  zunutze, komplexere und hierarchische Property-Ausdrücke aufzulösen.&lt;br /&gt;&lt;br /&gt;Anstatt beispielsweise den Kundennamen wie folgt zu binden,&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;h:inputText&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    id="name" value="#{customerController.name}"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;/h:inputText&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;setzt man ein &lt;span style="font-style: italic;"&gt;Formbean-&lt;/span&gt;Object davor:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;h:inputText&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    id="name" value="#{customerController.formBean.name}"&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;/h:inputText&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Die Formbean wird als normale Java-Bean implementiert:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;public class CustomerBean {&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;   private String name;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;   public void setName(String name) {&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;      this.name = name; &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;   }&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;   public String getName() {&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;      return name;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;   }&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Der Übersichtlichkeit kommt dies natürlich auch zugute, da der UI-Controller nicht mehr mit Gettern und Settern für alle Felder überschwemmt wird.&lt;br /&gt;&lt;br /&gt;Im Controller gibt es nun eine zentrale Stelle für die Initialisierung:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;public class CustomerController {&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;   public Object getFormBean() {&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;      if (formBean == null) {&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;         formBean = new CustomerBean();    &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;      &lt;br /&gt;       // load form data, set form properties, etc.&lt;br /&gt;       ... &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;      }&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;   &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;      return formBean; &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;   }  &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;   &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;   private CustomerBean formBean; &lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;Sobald erstmalig der Wert eines Feldes angefordert wird, wird die Formbean erzeugt - bei allen folgenden Property-Zugriffen wird die Initialisierung dann übersprungen.&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4412946060994304744-952983454470042228?l=voodoobits.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://voodoobits.blogspot.com/feeds/952983454470042228/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4412946060994304744&amp;postID=952983454470042228' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4412946060994304744/posts/default/952983454470042228'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4412946060994304744/posts/default/952983454470042228'/><link rel='alternate' type='text/html' href='http://voodoobits.blogspot.com/2008/03/jsf-und-die-frage-wie-es-losgeht.html' title='JSF und die Frage wie es losgeht'/><author><name>Stefan</name><uri>http://www.blogger.com/profile/09590954467358613683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4412946060994304744.post-2795920727888959457</id><published>2008-03-20T16:18:00.006+01:00</published><updated>2008-03-20T16:32:58.466+01:00</updated><title type='text'>JavaDB in 5 Schritten</title><content type='html'>Für einen ersten Test mit der JavaDB (früher Apache Derby, davor IBM sowie Cloudscape) habe ich ein bestehendes Oracle/Postgres-Schema mit etwa 60 Tabellen übertragen.&lt;br /&gt;Das ging erfreulich unkompliziert. Ebenso der anschließende Zugriff über Hibernate.&lt;br /&gt;Angepasst werden mussten lediglich:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;die ID-Vergabe aus Hibernate (statt Sequenzen nun Identity-Felder, durch Ableiten der SQL-Dialekte kann weiterhin mit bestehenden Entity-Annotations gearbeitet werden).&lt;/li&gt;&lt;li&gt;die JavaDB mag in Scripten keine &lt;span style="font-family:courier new;"&gt;NULL&lt;/span&gt;-Keywords hinter den Columns (&lt;span style="font-family:courier new;"&gt;NOT NULL&lt;/span&gt; fkt. selbstverständlich)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;1. Der Server kann durch die mitgelieferten Batchdateien gestartet werden. Das Setzen der Umgebungsvariablen &lt;span style="font-family:courier new;"&gt;DERBY_HOME&lt;/span&gt; ist gar nicht nötig.&lt;br /&gt;Im Falle von Windows:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;startNetworkServer.bat&lt;/span&gt; im Verzeichnis &lt;span style="font-family:courier new;"&gt;javadb\bin&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;2. Anlegen einer Datenbank mit dem Kommandozeilentool "ij":&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;connect 'jdbc:derby://localhost:1527/c:/JavaDB/db/myDB;create=true';&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;3. Beispiel zum Ausführen eines Scripts über ij:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;run 'c:\JavaDB\createDatabase.sql';&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;4. JDBC-Connections&lt;br /&gt;Der Treiber für den Client/Server-Betrieb ist &lt;span style="font-family:courier new;"&gt;org.apache.derby.jdbc.ClientDriver&lt;/span&gt;, für den Embedded-Mode &lt;span style="font-family:courier new;"&gt;org.apache.derby.jdbc.EmbeddedDriver&lt;/span&gt;.&lt;br /&gt;Für User + Passwort interessiert sich die JavaDB offenbar erst nach entsprechender Konfiguration.&lt;br /&gt;&lt;br /&gt;5. Shutdown&lt;br /&gt;Im Embedded-Mode erfolgt ein ordnungsgemäßes Herunterfahren durch &lt;span style="font-style: italic;"&gt;Anfordern einer Connection&lt;/span&gt;:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;DriverManager.getConnection("jdbc:derby:;shutdown=true");&lt;/span&gt;&lt;br /&gt;Eigentümlicherweise bedankt sich die JavaDB dabei standardmäßig mit einer Exception (Error-Code 50000).&lt;br /&gt;&lt;br /&gt;Weiteres:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Für den Embedded-Mode ist die Datenbank sofort nach Anfordern einer Connection über den DriverManager betriebsbereit.&lt;/li&gt;&lt;li&gt;Ohne weitere Änderungen werden nur lokale Verbindungen akzeptiert. Dies kann durch Ergänzen der Batchdatei mit folgendem Startparameter geändert werden:&lt;/li&gt;&lt;li&gt;  &lt;span style="font-family:courier new;"&gt;(... ) org.apache.derby.drda.NetworkServerControl start -h 0.0.0.0&lt;/span&gt; &lt;/li&gt;&lt;li&gt;In URLs für den Embedded-Treiber entfällt die Host-Angabe (z.B.: &lt;span style="font-family:courier new;"&gt;jdbc:derby:c:/JavaDB/db/myDB&lt;/span&gt;)&lt;/li&gt;&lt;li&gt;Hilfestellung gibt ij durch das help-Kommando&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Schließlich zur interessanten Frage: was ist mit der Performance ?&lt;br /&gt;Nun, der Mythos von der Langsamkeit von Java wird mit einer in Java geschriebenen Datenbank sicherlich auch nicht aussterben.&lt;br /&gt;Wie auch immer, der erste &lt;span style="font-style: italic;"&gt;Eindruck &lt;/span&gt;ist gut (einige Suchanfragen über 10000 Artikelsätze mit Joins und Subselects).&lt;br /&gt;Besonders interessant ist auf jeden Fall der Embedded-Mode für unkomplizierte Auslieferungen als Teil von Datenbank-Anwendungen oder für einen autarken JUnit-Testbetrieb.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4412946060994304744-2795920727888959457?l=voodoobits.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://voodoobits.blogspot.com/feeds/2795920727888959457/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4412946060994304744&amp;postID=2795920727888959457' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4412946060994304744/posts/default/2795920727888959457'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4412946060994304744/posts/default/2795920727888959457'/><link rel='alternate' type='text/html' href='http://voodoobits.blogspot.com/2008/03/javadb-in-5-schritten.html' title='JavaDB in 5 Schritten'/><author><name>Stefan</name><uri>http://www.blogger.com/profile/09590954467358613683</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry></feed>
