Intersult Abraxas ist ein Werkzeug für den Umgang mit XML-Dateien im Netzwerk-Umfeld. Beispiele sind Kommunikation mit SOAP, REST, Generieren von Java-Klassen, Serialisieren von Java-Objekten in XML und umgekehrt.
Das XML-Paket kann unter Maven 2/3 direkt aus dem Intersult Maven Repository bezogen werden. Für Rechte und Einsatz in kommerziellen Anwendungen nehmen Sie bitte Kontakt zu uns auf.
The XML Tools are accessible using the following ids:
group-id | com.intersult |
artifact-id | abraxas |
version | 1.3-SNAPSHOT |
The Maven Plugin is accessible under:
group-id | com.intersult |
artifact-id | abraxas-maven |
version | 1.3-SNAPSHOT |
The Remote-Service:
group-id | com.intersult |
artifact-id | abraxas-service |
version | 1.3-SNAPSHOT |
<build> ... <plugins> ... <plugin> <groupId>com.intersult</groupId> <artifactId>abraxas-maven</artifactId> <version>1.3-SNAPSHOT</version> <executions> <execution> <goals> <goal>generate-ws</goal> </goals> <configuration> <services> <service> ... </service> </services> </configuration> </execution> <executions> </plugin> ... </plugins> ... </build>
Unter <service> werden ein oder mehrere Services generiert. Unterhalb können weiter Parameter angegeben werden, die das Generieren der Servies steuern:
Parameter | Bedeutung |
---|---|
outputPath | Ausgabepfad für die generierten Klassen, in der Regel etwas wie ${project.build.directory}/generated-sources/weather |
wsdl | URL zur WSDL, zum Beispiel file:/${basedir}/src/main/resources/globalweather.wsdl oder kann auch direkt auf HTTP gehen. Durch Protocol-Plugins können auch weitere URLStreamHandler verwendet werden. |
packageName | Der Name der zu generierenden Packages. Falls er nicht angegeben wird, wird er aus dem Target-Namespace aus der WSDL generiert. |
ports * | Liste der zu generierenden "Ports", falls der Wert nicht angegeben wird, werden alle WSDL-Ports generert. Beispiel <ports><port>GlobalWeatherSoap</port></ports> |
operations* | Zu generierende WSDL-Operations. Wird der Wert nicht angegeben, werden alle Operations generiert. Beispiel wäre <operations><operation>GetWeather</operation></operations> |
xmlConfig | Konfiguration der XML-Verarbeitung durch Abraxas-XML, wie unter dem Abschnitt XML-Konfiguration beschrieben ist. |
protocol | Zu verwendender URLStreamHandler für den WSDL-URL, zum Beispiel <protocol implementation="com.intersult.testing.ServletUnitProtocol"> |
mappings | Hier können zusätzliche Mappings beim Erzeugen der Java-Klassen definiert werden. Dies ist ein sehr fortgeschrittenes Feature und für gewöhnlich nicht notwendig, da die generierten Klassen abgeleitet und im RemoteClient registriert werden können. |
Bei der Angabe von Ports und Operations werden (momentan) trotzdem alle Klassen aus dem eingebetteten XSD-Schema generiert.
Das Marshalling und Unmarshalling stellt ein Default-Verhalten zur Verfügung, das einen sehr weiten Bereich von denkbaren Java-Objekten abdeckt. Darüber hinaus besteht die Möglichkeit durch einige Annotations das Marshalling zu steuern.
String xml = "<java.lang.String>Test</java.lang.String>"; String string = (String)Xml.unmarshall(xml); System.out.println(string);
Erklärung: Die XML "Datei" wird direkt als String im Java-Code erzeugt und der lokalen Variablen xml zugewiesen. Danach wird mit die Methode marshall der Klasse com.intersult.xml.Xml aufgerufen, welche Strings, Streams und andere Quellen in Java-Objekte umwandelt (sog. Unmarshalling).
Folgendes Code-Beispiel zeigt einen Unmarshal-Marshal-Roundtrip:
Foo objectInput = new Foo(); objectInput.setValue("Test-Wert"); String xml = Xml.marshall(objectInput); System.out.println(xml); Foo objectOutput = (Foo)Xml.unmarshall(xml); System.out.println(objectOutput.getValue());
Mit Foo.java:
public class Foo { private String value; public String getValue() { return value; } public void setValue(String value) { this.value = value; } }
Parameter | Default | Bedeutung |
---|---|---|
validate | true | Damit kann das validieren gelesener XML-Dateien durch angegebene XSD- und DTD-Dateien abgeschaltet werden. |
writeEmpty | false | Legt fest, ob Null-Objekte geschrieben werden sollen. |
useDefault | false | Damit kann das Verarbeiten von Default-Annotationen eingeschaltet werden. |
writeId | false | Legt fest ob extra Attribute für IDs bei Arrays und Maps geschrieben werden sollen. |
encoding | UTF-8 | Legt das Encoding fest. |
writeType | NONE | Legt fest ob Java-Class-Namen geschrieben werden sollen. Bei NONE werden nur die einfachen Namen der Java-Properties geschrieben, außer beim Wurzel-Element falls dies keine Name- oder Namespace-Annotation enthält. Bei DERIVATES werden Klassennamen geschrieben, falls das Attribut von der Definition abweicht, also abgeleitet ist. Bei ALL werden die Typnamen immer geschrieben. |
throwUnknown | true | Damit können Exceptions abgeschaltet werden, die erzeugt werden wenn Attribut- und Elementnamen nicht auf die Java-Klassen gemappt werden können. |
mapping | - | Mappings für das Marshalling/Unmarshalling |
classLoader | XmlUnmarshaller.class.getClassLoader() | ClassLoader zum Laden von Klassen. |
attributeHandlers | Interne Handler | Handler welche die XML-Attribute verarbeiten, wie Namespace-Includes. |
pretty | true | Damit kann das Formattieren des generierten XML-Codes abgeschaltet werden. |
formatMap | Interne Formate | Registrierung von Klassen zur Formatierung von speziellen Objekten. |
namespaceStack | - | Zugriff auf den NamespaceStack der XML-Verarbeitung |
processIncludes | true | Damit können Schema-Include-Anweisungen komplett abgeschaltet werden. |
absoluteIncludes | true | Damit können absolute URLs bei Schema-Includes ausgeschaltet werden. |
throwDuplicate | true | Damit können die Exceptions bei konourrierenden Array- und Map-Einträgen abgeschaltet werden. |
usePrefix | false | Legt fest, ob die SOAP-Message ein Namespace-Prefix bekommen soll. |
processEnum | true | Legt fest, ob Enums generiert werden sollen. |
throwFault | true | Möglichkeit zum Abschalten von Exceptions bei SOAP-Faults. |
serializable | false | Damit können alle generierten Klassen serialisierbar gemacht werden. |
handleIds | true | Legt fest, ob ID-Angaben in Arrays und Maps verarbeitet werden. |
autoCdata | true | Legt fest, ob bei Bedarf automatisch CDATA-Elemente generiert werden sollen. |
logging | false | Legt fest, ob die XML-Kommunikation mitgeloggt werden soll. |
annotations | true | Legt fest ob Annotations generiert werden sollen. |
proxy | Proxy.NO_PROXY | Zu verwendendes java.net.Proxy |
connectTimeout | - | Timeout für die TCP-Connection. |
readTimeout | - | Timeout für das Lesen von der TCP-Connection. |
collectNamespace | true | Legt fest ob beim Generieren von XML die Namespace-Definitionen zuerst gesammelt werden und auf Dokumentenebene ausgegeben werden. Das reduziert Namespace-Definitionen und verkürzt damit das generierte XML. |
unwrap | false | Auspacken von Response-Klassen. Kann zu Fehlern führen, wenn die SOAP-Response-Messages mehrere Elemente enthalten. |
transparentNtlm | true | Experimentelles Feature zum Unterbinden von transparenter NTLM-Authentifizierung, falls der Client auf Windows-Rechnern läuft. |
induceTypes | true | Legt fest, ob bei der Schema-Induktion Typen wie Integer oder Datum automatisch erkannt werden oder ob standardmäßig xsd:string verwendet wird. |
induceNillable | false | Steuert ob bei der Schema-Induktion Felder als nillable gekennzeichnet werden. |
valueInducer | IntegerInducer, UrlInducer, DateTimeInducer | Liste von Objekten zum feststellen von Datentypen, die das Interface ValueInducer implementieren. Es handelt sich um eine Liste, die angepasst werden kann, um das Feststellen von Datentypen bei der Schema-Induktion zu unterstützen. |
minStrategy | LAX | Legt fest, mit welcher Strategie die minimale Anzahl von Child-XML-Elementen induziert wird (Schema-Attribut minOccurs). Default ist die LAX-Strategy, die ein Mindestauftreten eines Elements von 1 verlangt, wenn das Element in allen Fällen mindestens einmal vorkam und mindestens zwei Fälle vorliegen. |
maxStrategy | LAX | Legt fest, mit welcher Strategie die maximale Anzahl von Child-XML-Elementen induziert wird (Schema-Attribut maxOccurs). Default ist die MEDIUM-Strategie, die das Maximalauftreten eines Elements von UNBOUNDED erlaubt, sobald in einem Fall mindestens zwei Elemente aufgetreten sind. Hier ist keine LAX-Strategie sinnvoll, da maxOccurs per default als 1 angenommen wird, somit das Fehlen des Attributs zu einem Fehler beim Parsen der zuständigen XML führen würde. |
useStragegy | LAX | Legt die Strategie fest, mit der das use-Attribut "required" bei Attributen induziert wird. Default ist die LAX-Strategie, die required setzt, wenn in das attribut in allen Fällen vorhanden war und mindestens zwei fälle vorliegen. |
Um einen Web-Service auf SOAP-Basis anzusprechen, braucht man zunächst Java-Klassen, die die entsprechenden Daten übertragen. Diese werden aus der sogenannten WSDL (Web Service Description Language) generiert, die der SOAP-Service zur Verfügung stellt. Darin ist beschrieben, welche Methoden der Service anbietet und welche Objekte für die Kommunikation verwendet werden.
Die Generierung von Web Services aus WSDL-Dateien baut zum Teil auf der Generierung von XML-Schemata aus XSD-Dateien auf. Durch folgende Konfiguration kann ein Web Service Client generiert werden:
<project> ... <build> ... <plugins> ... <plugin> <groupId>com.intersult</groupId> <artifactId>abraxas-maven</artifactId> <version>1.3-SNAPSHOT</version> <executions> <execution> <goals> <goal>generate-ws</goal> </goals> <configuration> <services> <service> <outputPath>${project.build.directory}/generated/weather</outputPath> <wsdl>http://www.webservicex.net/globalweather.asmx?WSDL</wsdl> <packageName>net.webservicex.globalweather</packageName> </service> </services> </configuration> </execution> </executions> </plugin> ... </plugin> ... </build> ... </project>
Der Global Weather Service generiert einen Service, der durch folgenden Code ansprechbar ist:
GlobalWeatherSoap soap = new GlobalWeatherSoap(); GetWeatherResponse weather = soap.getWeather("nuernberg", "germany"); System.out.println(weather.getGetWeatherResult());
Dies kann in der pom.xml dann so aussehen:
<plugin> <groupId>com.intersult</groupId> <artifactId>abraxas-maven</artifactId> <version>1.3-SNAPSHOT</version> <executions> <execution> <id>generate-schema</id> <goals> <goal>generate-schema</goal> </goals> <configuration> <schemas> <schema> <xsdPath>${project.build.directory}/generated/web</xsdPath> <xsd>http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd</xsd> </schema> </schemas> </configuration> </execution> </executions> </plugin>
Das Beispiel zeigt, wie das XML-Schema der web.xml Version 2.5 über HTTP gestreamt wird und darauf Java-Klassen generiert. Dies kann eingesetzt werden, um Java-Klassen zu erzeugen mit der eine web.xml abgebildet werden könnte mit dem Zweck diese auszulesen oder zu generieren.
<service> <outputPath>${project.build.directory}/generated-sources/test</outputPath> <wsdl>unit://localhost/remote/HelloService?wsdl</wsdl> <packageName>com.intersult.hello</packageName> <xmlConfig> <unwrap>true</unwrap> </xmlConfig> <protocol implementation="com.intersult.testing.ServletUnitProtocol"> <webXmlFile>${basedir}/src/main/webapp/WEB-INF/web.xml</webXmlFile> </protocol> </service>
Beim Aufruf des Service kann der Handler ebenfalls lokal verwendet werden:
ServletUnitProtocol protocol = new ServletUnitProtocol(); URL serviceUrl = new URL(null, HelloService.SERVICE_URL, protocol); HelloService helloService = new HelloService(serviceUrl, Transport.SOAP);
<plugin> <groupId>com.intersult</groupId> <artifactId>abraxas-maven</artifactId> <version>1.3-SNAPSHOT</version> <executions> <execution> <id>generate-ws</id> <goals> <goal>generate-ws</goal> </goals> <configuration> <protocols> <com.intersult.testing.httpunit.HttpUnitProtocol> <webXmlFile>${basedir}/src/main/webapp/WEB-INF/web.xml</webXmlFile> <translateProtocol>false</translateProtocol> </com.intersult.testing.httpunit.HttpUnitProtocol> </protocols> <services> <service> <outputPath>${project.build.directory}/generated/test</outputPath> <wsdl>unit://localhost/remote/HelloService?wsdl</wsdl> <packageName>com.intersult.hello</packageName> <xmlConfig> <unwrap>true</unwrap> </xmlConfig> </service> </services> </configuration> </execution> </executions> <dependencies> <dependency> <groupId>com.intersult</groupId> <artifactId>testing</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> </plugin>
Das Artifact mit dem entsprechenden Protocol wird also als Dependency des Abraxas Plugin hinzugefügt. Damit sind die entsprechenden Klassen während der Ausführung des Abraxas Plugins im Classpath zugreifbar und können in der Konfiguration unter "protocols" hinzugefügt und selbst mit Parametern versehen werden.
Es ist nicht immer sinnvoll, Protokolle durch die ProtocolFactory systemweit zu registrieren.
Die Induktionsstrategien sind generell so ausgelegt, dass das Parsen des zur Induktion verwendeten XML-Dokuments positiv verläuft. Anders ausgedrückt, erzeugt die Induktion ein XML-Schema, innerhalb dessen das zur Induktion verwendete XML-Dokument gültig ist. Dies gilt für alle mitgelieferten Strategien.
Da die Strategien vom Nutzer abgeleitet werden können, können damit Schemata erzeugt werden, innerhalb derer das gegebene XML-Dokument ungültig wird. Das Ableiten der Strategien ist daher mit der entsprechenden Vorsicht zu verwenden.
Parameter | Beschreibung |
---|---|
resourceRoot | Ermöglicht das Einbinden als Resource-Pfad in den Build-Prozess. Der Parameter ist optional, durch Angabe ist es möglich die generierten XSD-Dateien in das Artifakt einzubinden. Beispiel wäre <resourceRoot>${project.build.directory}/generated-resources/xsd</resourceRoot> |
protocols | Ermöglicht das Einbinden globaler Protocols, wie bei generate-ws oder generate-schema. |
outputFile | Datei des zu generierenden Schemas, der Pfad wird komplett angelegt falls er noch nicht existiert. Beispiel wäre <outputFile>${project.build.directory}/generated-resources/xsd/simple.xsd</outputFile> |
xml | URL auf eine XML-Datei, aus der das Schema generiert werden soll. |
targetNamespace | Optional kann der Target-Namespace manuell festgelegt werden. Standardmäßig wird er aus der XML-Datei entnommen, falls dort xmlns oder xmlns:<tns> Angaben vorhanden sind. |
prefix | Optional kann das zu verwendende Prefix angegeben werden. Andernfalls wird es aus der verarbeiteten XML-Datei entnommen. |
xmlConfig | Zugriff auf die XmlConfig, mit der Möglichkeit entsprechende Werte zu setzen. Insbesondere interessant sind hier die Strategie-Angaben zur Induktion von Anzahl und Typen. |
protocol | Optionale Angabe eines Protocols, das beim Zugriff auf die XML-Datei benutzt wird. |
<plugin> <groupId>com.intersult</groupId> <artifactId>abraxas-maven</artifactId> <version>1.3-SNAPSHOT</version> <executions> <execution> <id>induce-schema</id> <goals> <goal>induce-schema</goal> </goals> <configuration> <inducers> <inducer> <xml>file:/${basedir}/src/main/resources/simple.xml</xml> <outputFile>${project.build.directory}/simple.xsd</outputFile> </inducer> </inducers> </configuration> </execution> </executions> </plugin>
Die XSD-Datei wird hier im Target generiert. Falls die Ressource-Root zum Build-Path hinzugefügt werden soll, kann dies mit dem Parameter <resourceRoot>...path...</resourceRoot> gemacht werden.
Ansonst kann die erzeugte XSD auch verwendet werden, um mit generate-schema in einem weiteren Execution-Schritt die Java-Klassen zu generieren.
SchemaInducer inducer = new SchemaInducer(); InputStream inputStream = getClass().getResourceAsStream("induce.xml"); Xsd xsd = inducer.induce(inputStream); xsd.write(System.out);