Serverkonfiguration im JBoss
Im MBean “jboss.system:service=ServerConfig” ist die Serverkonfiguration vom JBoss einsehbar. Darauf hat man auch ganz leicht Zugriff im Java selbst:
(weiterlesen…)
Kai Freikorps Kai Tracid Kai Winding
buy CD Albireon download music Apparat download albums After The Eulogy albums download 2 Preciious, Lee Aaron Arthur Cordewener A Beautiful Machine Absolum online tracks Audioholics Alio Die and Zeit A Beautiful Machine Absolum buy albums Animal Collective (feat. Vashti Bunyan) download music Artento Divini online music AZ-Rotator buy tracks Alfven, Hugo buy Arizona Dream A Beautiful Machine albums buy Alexi Delano buy albums Andy Moor Annie Haslam A Beautiful Machine Absolum download CD 2Pac - Makaveli and Dillinger Accept A Beautiful Machine Absolum online albums Agresion buy CD Apparat Amsterdam Klezmer Band A Beautiful Machine Absolum online CD Acid Rain buy Anugama and Sebastiano A Beautiful Machine buy music A Split Second albums download Apocalypse download Asrai A Beautiful Machine download mp3 2 Preciious, Lee Aaron online mp3 Adam Freeland online CD A-Ha buy tracks 4 Strings and Tina Cousins buy CD Artie Shaw online CD AZ download music Amauta and Rijchary buy music ASC feat Intex Systems buy tracks Arruga, Lombardo and Friends buy music Ashen Light download Aidan Baker vs. Cymbl A Beautiful Machine albums buy Angels and Airwaves download Astrid Williamson A Beautiful Machine Akwid and Jae-P A Beautiful Machine Absolum online CD Alejandro Sanz buy tracks Aly and Fila buy tracks Alex Sword and John Chevalier online mp3 Abazagorath albums download Arthur Alexander download albums Anchors for Arms download CD Anuradha Paudwal, Sanjeev Ab.. albums download Altiplano De Chile download tracks Acron online albums Auberon buy mp3 A New Age In Relaxation online mp3 Avail albums download Angelo Badalamenti download Alan Menken A Beautiful Machine buy tracks Arcane online tracks Alternative Control online Agatus A Beautiful Machine download CD Adham Shaikh download music 68 Beats download music Alan Sorrenti buy CD Arj Snoek download Aidan Baker A Beautiful Machine download CD Akira Takasaki buy music Anathema online mp3 Alla Zagaykevych online Altus and Silvercord A Beautiful Machine download mp3 Arnold Schoenberg and Anton Webern buy mp3 Alexander online Aes Dana A Beautiful Machine download mp3 5Ive's Continuum Research Project buy mp3 Alastair Galbraith buy albums A Javelin Reign buy music Arzu buy mp3 Ahmed Sahin download tracks Apache Indian download CD Alex Parsons and Tommy Four Seven Aalto A Beautiful Machine Absolum
Im MBean “jboss.system:service=ServerConfig” ist die Serverkonfiguration vom JBoss einsehbar. Darauf hat man auch ganz leicht Zugriff im Java selbst:
(weiterlesen…)
Um ein MBean, wie z.B. einen TreeCache, auch per JNDI zur Verfügung zu stellen, muss lediglich ein weiteres MBean erstellt werden. Dazu wird in die entsprechende Service.xml-Datei folgender Code am Ende eingefügt: (weiterlesen…)
Der JBoss Cache, ein Memory-Cache mit Replikation über mehrere Nodes, lohnt sich als MBean zu verwenden. Der Zugriff auf das MBean läuft dann, wie auch in der Dokumentation beschrieben, wie folgt: (weiterlesen…)
Um von Außen auf Objekte des JBoss-Servers zugreifen zu können, welche per JNDI zur Verfügung gestellt werden, muss einfach JNDI beim Client entsprechend konfiguriert werden. Dazu reichen wenige Zeilen um darauf zu zugreifen: (weiterlesen…)
JBossWS 1.0 unterstützt noch nicht das direkte Nutzen von enums in Webservices. Dies ist erst bei der Unterstützung von JAXB-2.0 möglich. Bis dahin müssen Enums im J2EE 1.4 Enum-Stil implementiert werden. (weiterlesen…)
Eine gängie Suche bei Dokumenten z.B. ist die Suche in bestimmten Zeiträumen oder auch bei Produkten die Filterung nach Preisen. Lucene bietet dafür zwei Möglichkeiten an, welche sich in der Ausführungsart und im Ausführungszeitpunkt unterscheiden. RangeQuery ist eine Einschränkung für eine Abfrage um einen Wert entsprechend zu begrenzen. Wenn der QueryParser verwendet wird, so lautet die Syntax:
field:[2002 TO 5000]
. Statt den eckigen Klammern können auch geschweifte Klammern verwendet werden um die Werte 2002 und 5000 nicht mit in die Suche einzubeziehen. RangeQuery arbeitet intern als Booleanquery. Beim erstellen sucht es aus dem Index alle Terme heraus, die in die Grenzen passen, und erzeugt daraus ein entsprechendes BooleanQuery. In unserem Fall wohl 2002 OR 2003 OR 2004 OR …. OR 5000. Das Problem hierbei ist, dass schnell die maximale Grenze von BooleanQuery erreicht wird. Diese liegt standardmäßig bei 1024 und kann mit BooleanQuery.setMaxClauseCount() verändert werden. Bis ins unendliche sollte dies jedoch aus Speicher und Ausführungsgründen nicht getrieben werden. Es ist hier also schon absehbar, dass RangeQuery zwar schön und schnell einsetzbar ist und auch die Suche entsprechend schnell ist, jedoch nur bei eine begrenzten Anzahl an Termen einsetzbar.
Für unseren Fall, sofern zwischen 2002 und 5000 (fast) jedes Element vorhanden ist, bietet sich daher der RangeFilter an. Dieser baut ein Bitset über die Dokumente vor der Suche auf, welches die Zugehörigkeit der Dokumente zur Range entsprechend angibt. Dadurch ist dies natürlich etwas langsamer und entsprechend Speicherintensiver bei sehr großen Indizies. Es bietet sich jedoch vor allem bei Preissuchen, etc. an. Bei der Indizierung von Double-Werten z.B. sollte man jedoch darauf achten diese mit Vornullen zu indizieren, da sonst bei der Sortierung und bei RangeQuery / RangeFilter die Reihenfolge unerwartete Ergebnisse liefert.
Ohne Vornullen:
0.12 1.10 1.32 10.123 2.12 5.60
Mit Vornullen:
00000.12 00001.10 00001.32 00002.12 00005.60 00010.123
Das Suchframework Lucene bietet einem viele Möglichkeiten das Framework an seine Bedürfnisse anzupassen. Ein Punkt ist z.B. eine eigene Sortierung der Suchergebnisse. Die Implementierung gestaltet sich hierbei zudem denkbar einfach. Es muss lediglich das Interface SortComparatorSource sowie ScoreDocComparator implementiert werden.
Interessant ist vor allem das zweite Interface, da hier der eigentliche Vergleich zweier Dokumente betrachtet wird. Um den Zugriff auf indizierte Felder zu beschleunigen und vor allem zu cachen, bietet Lucene ebenfalls hauseigene Mittel an, die auch in der eigenen String- und Ganzzahlsortierung mit genutzt werden. Der Zugriff darüber läuft über das Interface FieldCache und dessen Implementierung FieldCache.DEFAULT.
Hin und wieder hat man bei @ManyToOne und @ManyToMany Beziehungen zwischen Entitäten auch noch Attribute zu hinterlegen. Ein weiterer Anwendungsfall, dann halt ohne Attribute, ist die Auslagerung der ManyToOne-Beziehung in eine eigene Tabelle. Hibernate, welches mit dem JBoss 4.0.4.GA ausgeliefert wird, unterstützt leider derzeit noch keine @JoinTable in Verbindung mit @OneToOne oder @ManyToOne. Das Mapping wird beim Deployment mit folgendem Fehler quittiert:
org.hibernate.cfg.NotYetImplementedException: association table on a single ended association is not yet supported
Es bleibt einem daher nichts anderes übrig, als die Beziehung als eigene Entität zu implementieren. In unserem Beispiel haben wir hier eine Klasse A und eine Klasse B, welche zusammen die Beziehung ManyToOne haben und diese in der Tabelle A2B gespeichert wird. Die Klassen sehen dann so aus:
@Entity public class A { @Id private int id; @OneToOne(fetch = FetchType.LAZY, mappedBy = “a”) private A2B a2b; } @Entity public class B { @Id private int id; @OneToOne(fetch = FetchType.LAZY, mappedBy = “b”) private A2B a2b; } @Entity public class A2B { @EmbeddedId @AttributeOverrides( { @AttributeOverride(name = “aId”, column = @Column(nullable = false)), @AttributeOverride(name = “bId”, column = @Column(nullable = false)) }) private A2BId id; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = “aId”, insertable = false, updatable = false) private A a; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = “bId”, insertable = false, updatable = false) private B b; } @Embeddable public class A2BId implements Serializable { private int aId; private int bId; @Override public boolean equals(Object other) { if ((this == other)) return true; if ((other == null)) return false; if (!(other instanceof A2BId)) return false; A2BId castOther = (A2BId) other; return (aId == castOther.aId) && (bId == castOther.bId); } @Override public int hashCode() { int result = 17; result = 37 * result + aId; result = 37 * result + bId; return result; } }
Wichtig hierbei ist der eigene PrimaryKey in Form eines @Embeddable - Objektes sowie das doppelte Mapping der Primary-Key-Spalten in der Beziehungstabelle. Wichtig ist hier, dass insertable und updateable beim zweiten Mapping auf false sind:
@JoinColumn(name = “aId”, insertable = false, updatable = false)
An die Klasse A2B könnten nun noch die angesprochenen weiteren Attribute gehangen werden zu der Beziehung. Um aus der ManyToOne eine ManyToMany-Beziehung auf Seiten von A und B zu machen, muss dort lediglich eine Collection der entsprechenden Beziehungsklasse angelegt werden und entsprechend statt mit @OneToOne mit @OneToMany gemappt werden.
Wie bereits beim Release des JBoss 4.0.4 GA erwähnt, können jetzt Webservices mit Hilfe von Annotations erstellt werden. Dies möchte ich hier am Beispiel eines POJO-Webservices zeigen.
Dazu erstellen wir uns einfach eine Klasse, welche die Logik des Webservices enthält.
package com.it_blogger.webservices; import javax.jws.WebMethod; import javax.jws.WebService; import javax.jws.soap.SOAPBinding; @WebService @SOAPBinding(style = SOAPBinding.Style.RPC) public class TestWebservice { @WebMethod public String hello(String name) { return “Hello “+name+“!”; } }
Dieser Klasse geben wir einfach die Annotation @WebService mit und zudem jeder öffentlich zugänglichen Methode noch @WebMethod. Damit sind wir mit dem Webservice schon fertig. Jetzt muss das Ganze noch gepackt werden. Dazu wird die Klasse einfach wie ein Servlet in einer WAR-Datei deployed. Die web.xml kann z.B. so aussehen:
<?xml version=”1.0″?> <web-app xmlns=“http://java.sun.com/xml/ns/j2ee“ xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance“ xsi:schemaLocation=“http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd“ version=“2.4“> <servlet> <servlet-name>TestWebservice</servlet-name> <servlet-class> com.it_blogger.webservices.TestWebservice </servlet-class> </servlet> <servlet-mapping> <servlet-name>TestWebservice</servlet-name> <url-pattern>/TestWebservice</url-pattern> </servlet-mapping> </web-app>
Jetzt kann unter http://localhost:8080/jbossws/ der Link für den entsprechenden Webservice abgerufen werden.
Die WAR-Datei kann zudem um eine JBoss-Web.Xml erweitert werden, um den Webservice auf einem bestimmten VirtualHost zu deployen. Leider wird in der WSDL-Datei der Endpunkt derzeit noch nicht dynamisch angepasst. Die jboss-web.xml, welche ebenfalls in das WEB-INF-Verzeichnis der WAR-Datei muss, sieht dann entsprechend so aus:
<?xml version=”1.0″ encoding=“UTF-8″?> <jboss-web> <context-root>/</context-root> <virtual-host>webservices.it-blogger.com</virtual-host> </jboss-web>
Um auf per JAAS geschützte Methoden zugreifen zu können muss der Aufrufer sich entsprechend eingeloggt haben. Dabei wird unter JAAS ein sogenannter LoginContext erstellt.
import javax.security.auth.login.LoginContext; public class MyClass { … public void login() throws UnsupportedEncodingException, LoginException { ClassLoader cl = Thread.currentThread().getContextClassLoader(); URL authconf = cl.getResource(“jaas.conf”); String p = URLDecoder.decode(authconf.toExternalForm(), “UTF-8″); System.setProperty(“java.security.auth.login.config”, p); auth = new LoginContext(“mycontext”, new SimpleLoginCallbackHandler(“user”, “password” .toCharArray())); auth.login(); } … }
Wichtig hierbei ist der LoginCallbackHandler, wobei hier ein eigener SimpleLoginCallbackHandler verwendet wird, und die jaas.conf, welche die JAAS-Konfiguration enthält.
Da wir uns in den JBoss einloggen möchten, sieht die jaas.conf wie folgt aus:
mycontext {
org.jboss.security.ClientLoginModule required;
};
Der verwendete CallbackHandler gibt lediglich die per Constructor übergebenen Parameter zurück:
import java.io.IOException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.UnsupportedCallbackException; public class SimpleLoginCallbackHandler implements CallbackHandler { private String userName; private char[] password; public SimpleLoginCallbackHandler(String userName, char[] password) { this.userName = userName; this.password = password; } public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (Callback callback : callbacks) { if (callback instanceof NameCallback) { ((NameCallback) callback).setName(userName); } else if (callback instanceof PasswordCallback) { ((PasswordCallback) callback).setPassword(password); } } } }
Ein Logout kann entsprechend über den LoginContext wieder erfolgen:
public class MyClass { … public void logout() throws LoginException { auth.logout(); } … }
Wenn der Client direkt im JBoss läuft, also z.B. als Servlet im Tomcat oder als MBean, so wird keine jaas.conf benötigt. In diesem Fall wird einfach ein LoginContext erstellt mit dem Namen “client-login”.