Archiv für August, 2006

SSL und somit auch https nutzen eine asysmetrische Verschlüsselung, d.h. der Client benötigt den öffentlichen Schlüssel des Servers, mit dem er die Nachricht für diesen verschlüsseln kann.

Um mit einem Java-WebService-Client eine SSL Verbindung herzustellen, muss das Zertifikat des Servers in den JVM Keystore importiert werden. Man kann es entweder in den Standardkeystore importieren, der je nach Betriebssystem an verschiedenen Orten liegen kann. Bei Windows liegt er normalerweise hier:

C:\Dokumente und Einstellungen\<user>\.keystore

Um einen Zertifikat und somit einen Schlüssel in diese Datei zu importieren, kann man das Keytool von SUN nutzen, welches unter %JAVA_HOME%\bin\keytool.exe zu finden ist. Ein Import eines Zertifikates sieht folgendermaßen aus:

keytool -import -v -alias <keyalias – frei wählbar> -file <Speicherort des Zertifikats> -storepass <standard:changeit>

Leider scheint Tomcat warum auch immer partout nicht auf diese Datei zuzugreifen, also habe ich eine eigene Datei mit dem zusätzlichen Parameter -keystore <datei.keystore> erstellt.

Nun musste ich auch noch beim Initialisieren meines Servlet, welches den WebService über https aufruft das System-Property javax.net.ssl.trustStore setzen:

System.setProperty(„javax.net.ssl.trustStore“, „datei.keystore“);

Für den Client MUSS es das trustStore-Property sein und NICHT das keyStore-Property.

Das ganze kann man natürlich auch Tomcat als Startparameter mit übergeben, wie hier beschrieben.

Update: Der java-weite Keystore liegt in JAVA_HOME\jre\lib\security\cacerts

Nach längerem Suchen habe ich endlich verstanden, wie man n:m-Beziehungen in Hibernate am besten mappt.
Für die Verwaltung von solchen Beziehungen benötigt man in relationalen Datenbanken eine Beziehungstabelle.

Nehmen wir an es gibt 3 Tabellen:

News, Category und NewsCategory.

Eine News kann mehreren Categories zugeordnet sein und die Categories können natürlich in verschiedenen News benutzt werden. NewsCategory ist somit die Relationship-Tabelle.

Folgende Felder sind definiert (Auszug):

  • News-Tabelle: newsId(PK)
  • Category-Tabelle: categoryId(PK)
  • NewsCategory-Tabelle: newsCategoryId(PK), newsId(FK), categoryId(FK)

In der news.hbm.xml-Mapping-Datei definiert man ein Set, das die Beziehung zu den Categories abbildet:

<set name=“categories“ table=“NewsCategory“>
<key column=“newsId“ />
<many-to-many class=“net.vland.demo.Category“ column=“categoryId“/>
</set>

Das gleiche in der category.hbm.xml

<set name=“news“ table=“NewsCategory“>
<key column=“categoryId“ />
<many-to-many class=“net.vland.demo.News“ column=“newsId“/>
</set>

Nun muss man nur noch in den POJOs einfache Sets mit den definierten Namen erzeugen und das war’s. Es ist jetzt möglich ohne Umwege über die Beziehungstabelle die Daten auszulesen, z.B.:

Set categories = news.getCategories();

Anmerkung: Hibernate wirft eine Exception, wenn für einen Datensatz kein „Beziehungs-Set“ da ist. Dies kann durch not-found=“ignore“ im <many-to-many>-Tag unterbunden werden.

Wenn ein Hibernate-Property mit einem Kleinbuchstaben anfängt und darauf ein Groß-Buchstabe folgt, funktionieren die Getter und Setter, die Eclipse generiert, nicht mehr.

Das Property heißt tEinkaeufer.

Dafür hat Eclipse diese Getter und Setter generiert:

public TEinkaeufer getTEinkaeufer()
{
return tEinkaeufer;
}

public void setTEinkaeufer(TEinkaeufer einkaeufer)
{
tEinkaeufer = einkaeufer;
}

Beim initialisieren von Hibernate wurde dann folgender Fehler geworfen:

Initial SessionFactory creation failed.org.hibernate.PropertyNotFoundException: Could not find a getter for tEinkaeufer in class …

Daraufhin habe ich den Code folgendermaßen abgeändert:

public TEinkaeufer gettEinkaeufer()
{
return tEinkaeufer;
}

public void settEinkaeufer(TEinkaeufer einkaeufer)
{
tEinkaeufer = einkaeufer;
}

Und nun funktioniert es, was mich ein bisschen wundert.

Ich weiß nicht ob das ein Fehler in Hibernate ist, oder ob das so gewollt ist. Kann mir nicht vorstellen wieso…

Für den Web Service, der die Einkäuferdaten liefern soll, hab ich mit den HibernateTools Klassen und hbm.xml-Dateien generieren lassen.

Das ging soweit auch ganz gut. Nun gibt es aber anscheinend Tabellen in der zu integrierenden Datenbank, die keinen Primary Key haben!

Aus diesen machen die Tools dann zusammengesetze Primärschlüssel, und zwar aus allen Attributen der Tabelle.

<!– Generated 11.07.2006 15:42:45 by Hibernate Tools 3.1.0.beta5 –>
<hibernate-mapping>
<class name=”net.cpu.diplomarbeit.data.db.TEinkaeufer” table=”T_Einkaeufer” schema=”dbo” catalog=”EinkaeuferDB”>
<composite-id name=”id” class=”net.cpu.diplomarbeit.data.db.TEinkaeuferId”>
<key-property name=”telvPersnr” type=”string”>
<column name=”telvPersnr” length=”9″ />
</key-property>
<key-property name=”telvName” type=”string”>
<column name=”telvName” length=”50″ />
</key-property>
<key-property name=”telvVorname” type=”string”>
<column name=”telvVorname” length=”30″ />
</key-property>
<key-property name=”telvKostenstelle” type=”string”>
<column name=”telvKostenstelle” length=”10″ />
</key-property>
<key-property name=”telvAbteilung” type=”string”>
<column name=”telvAbteilung” length=”40″ />
</key-property>
<key-property name=”telvEmail” type=”string”>
<column name=”telvEmail” length=”128″ />
</key-property>
<key-property name=”telvTelefon” type=”string”>
<column name=”telvTelefon” length=”63″ />
</key-property>
<key-property name=”telvFax” type=”string”>
<column name=”telvFax” length=”63″ />
</key-property>
<key-property name=”telvMobExt” type=”string”>
<column name=”telvMobExt” length=”63″ />
</key-property>
<key-property name=”telvFirma” type=”string”>
<column name=”telvFirma” length=”60″ />
</key-property>
<key-property name=”telvPostfach” type=”java.lang.Integer”>
<column name=”telvPostfach” />
</key-property>
<key-property name=”telvStrasse” type=”java.lang.Integer”>
<column name=”telvStrasse” />
</key-property>
<key-property name=”telvPlz” type=”java.lang.Integer”>
<column name=”telvPLZ” />
</key-property>
<key-property name=”telvOrt” type=”string”>
<column name=”telvOrt” length=”60″ />
</key-property>
<key-property name=”telvLand” type=”string”>
<column name=”telvLand” length=”3″ />
</key-property>
<key-property name=”telvGesellschaft” type=”string”>
<column name=”telvGesellschaft” length=”40″ />
</key-property>
<key-property name=”telvBereichKurz” type=”string”>
<column name=”telvBereichKurz” length=”40″ />
</key-property>
<key-property name=”telvBereichDe” type=”string”>
<column name=”telvBereich_de” />
</key-property>
<key-property name=”telvBereichEn” type=”string”>
<column name=”telvBereich_en” />
</key-property>
<key-property name=”telvWerkName” type=”string”>
<column name=”telvWerkName” length=”60″ />
</key-property>
</composite-id>
</class>
</hibernate-mapping>

Ich muss allerdings eine 1:n Relation zu einer solchen Tabelle erstellen und da gibt es näturlich eine Fehlermeldung, da der Primärschlüssel mehre Attribute enthält und der Fremdschlüssel darauf nur eines. Deshalb musste ich diese Klasse von Hand umstrukturieren und einen Primärschlüssel setzen.

<id name=”telvEmail” type=”string”>
<column name=”telvEmail” length=”128″/>
</id>

Da ich die Daten nur auslesen muss, sollte es keine Probleme geben. Beim Schreiben muss dieser Primärschlüssel dann eben von Hand gesetzt und auf Eindeutigkeit geprüft werden.

Beim „Contract First“ Ansatz für WebServices generiert man zuerst die WSDLs und dazugehörigen XML Schema-Dateien, um daraus dann mit WSDL2Java ein Java Bean Skeleton zu erzeugen.

Wenn dann die URL des WebServices mit ?wsdl aufgerufen wird, generiert AXIS aus den Klassen mit Java2WSDL wieder eine WSDL Datei.

Allerdings gibt es da ein Problem mit annonymen inneren ComplexTypes, wenn ein Element maxOccurs=“unbounded“ definiert ist.

Der XSD-Ausschnitt, der den Fehler:

Server.generalException – makeTypeElement() was told to create a type […]

generierte, sah folgendermaßen aus:

<complexType name=“searchItemListType“>
<sequence>
<element maxOccurs=“unbounded“ name=“searchItem“ />
<complexType> <– annonymous inner type
<sequence>
<element ref=“tns:id“/>
<element name=“name“ type=“string“/>
</sequence>
</complexType>
</element>
</sequence>
</complexType>

D.h. also, der Typ für das searchItem-Element hat keine Bezeichnung. Und ich denke hier lag mein Denkfehler.

Wie soll WSDL2Java Klassen (also Typen) erstellen für Arrays ohne einen Namen zu haben.

Deshalb sieht die Lösung folgendermaßen aus:

<complexType name=“searchItemListType“>
<annotation>
<documentation>Type for all searchItems with id and itemtext in the selected language</documentation>
</annotation>
<sequence>
<element maxOccurs=“unbounded“ name=“searchItem“ type=“tns:searchItemType“/>
</sequence>
</complexType>

<complexType name=“searchItemType“>
<sequence>
<element ref=“tns:id“/>
<element name=“name“ type=“string“/>
</sequence>
</complexType>

So funktioniert nun auch Java2WSDL und zeigt die WSDL-Datei problemlos an.

Bei der Einbindunge eines XML iViews muss man als letzten Schritt einen Transformator zur Darstellung der XML-Datei angeben:

Solche Tranformatoren lassen sich auch selbst erstellen, indem man eine Portal Applikation (.PAR) erstellt. Mit der einfachen Angabe einer XSL-Datei ist es dabei nicht getan, aber es ist nicht viel schwieriger, zumindest nicht für einfache Transformatoren-Provider.

Simple Providers (SAP-Bibliothek – SAP NetWeaver Developer’s Guide)

Diese Provider sprechen anscheinend den standardmäßigen Transformation Service von Netweaver an. Die bereits installierten Standard-Transformatoren transformieren das XML zunächst in das SAP-proprietäre XHTMLB Format. Der danach folgende Transformator muss das Ganze dann in das HTMLB Format transformieren, welches die Portal-Laufzeitumgebung unterstützt und welches dann im iView angezeigt werden kann.

Habe heute weiter an der Doku geschrieben und dabei einen ersten Entwurf der Zielsetzung verfasst:

Als IT-Dienstleister für große Unternehmen muss man sich des öfteren auf Änderungen im IT-Umfeld einstellen. Die Ausrichtung auf neue Applikationsserver bzw. Integrationsplattformen wäre eine solche. In meinem Fall handelt es sich hierbei um das Produkt Netweaver von SAP und das dazugehörige Enterprise Portal, auf welches ein Kunde meines Ausbildungsbetriebs mittelfristig umstellt.

Die Zielsetzung dieser Diplomarbeit ist es, Möglichkeiten zu evaluieren, wie bestehende Anwendungen in diese neue Plattform integriert werden können.

Dies soll anhand einer zu bestimmenden Beispielanwendung geschehen, welche so gut wie möglich in das Portal des Kunden eingepasst werden soll. Dazu kann es nötig sein, einen Prototyp zu implementieren und für den Kunden zum Testen bereitzustellen.

Mit den Ergebnissen dieser Diplomarbeit soll erreicht werden, dass auch für zukünftige Applikationen die Integration in das neue System des Kunden so effizient wie möglich umgesetzt werden kann und man gleich im Planungsprozess die neuen Umstände mit einkalkulieren kann.

re

Zurück aus dem Urlaub, einen Tag später als geplant, weil mein Cousin noch einen Tag länger geblieben ist…