PropertyChangeListener generieren mit JAXB (xjc)

brookman

Neues Mitglied
Hallo zusammen!

Da ich jetzt schon seit vielen Stunden mit dem obigen Thema am kämpfen bin und nicht mehr weiter weiss, dachte ich, ich könnte es ja mal hier probieren. :)

Ich würde gerne aus XML-Schemata Java-Beans generieren, die PropertyChangeListeners enthalten. Dazu benutze ich Maven mit einem JAXB plugin und einem "listener code injector".

Bis jetzt funktioniert auch alles, bis auf Tatsache, dass der injector VetoableChangeListeners statt PropertyChangeListeners generiert.
Beispiel:
Java:
public void setCol(Integer value) {
        try {
            support.fireVetoableChange("col", this.col, value);
        } catch (PropertyVetoException _x) {
            return;
        }
        this.col = value;
    }

Auf Around the World in Java: Java XML Binding with Property Change Support habe ich zwar eine Anleitung gefunden (li:listener>java.beans.PropertyChangeListener</li:listener> im XML einfügen). Allerdings führt dies zu solchen listenern:

Java:
public void setCol(Integer value) {
        support.firePropertyChange("col", this.col, value);
        this.col = value;
    }
anstatt korrekterweise:
Java:
    public void setCol(Integer value) {
        Integer oldValue;
        oldValue = this.col;
        this.col = value;
        support.firePropertyChange("col", oldValue, value);
    }


Hier mein POM-Snipplet:
[XML]
<!-- JAXB class generation plugin configuration (XSD -> Java) -->
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<!-- <version>0.7.3</version>-->
<executions>
<execution>
<id>generate-java-classes</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>

<configuration>
<episode>false</episode>
<extension>true</extension>
<removeOldOutput>true</removeOldOutput>
<clearOutputDir>true</clearOutputDir>
<forceRegenerate>true</forceRegenerate>
<strict>true</strict>

<args>
<arg>-Xinject-listener-code</arg>
<arg>-Xboolean-getter</arg>
</args>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>gettersetter</artifactId>
<version>0.4.1.5</version>
</plugin>
</plugins>


<includeBindings>
<includeBinding>src/main/resources/schemas/bindings.xjb</includeBinding>
</includeBindings>
<schemaDirectory>src/main/resources/schemas</schemaDirectory>
<schemaIncludes>
<include>**/*.xsd</include>
</schemaIncludes>

</configuration>

<dependencies>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-xjc</artifactId>
<version>2.1.13</version>
</dependency>
<dependency>
<groupId>org.jvnet.jaxb2-commons</groupId>
<artifactId>property-listener-injector</artifactId>
<version>1.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-xjc</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</plugin>
[/XML]

Hier das "general.xsd", welches von allen anderen XSDs eingebunden wird (mit besagter Listener-konfiguration):
[XML]<?xml version="1.0" encoding="utf-8" ?>
<xs:schema xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:ci="http://jaxb.dev.java.net/plugin/listener-injector" jaxb:version="2.1"
jaxb:extensionBindingPrefixes="xjc ci" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="general" xmlns:general="general">

<xs:annotation>
<xs:appinfo>
<ci:listener>java.beans.PropertyChangeListener</ci:listener>
<jaxb:globalBindings localScoping="toplevel" collectionType="com.abc.asdf.binding.AdvancedArrayList" generateIsSetMethod="false" enableJavaNamingConventions="false">
<jaxb:javaType name="java.lang.Integer" xmlType="xs:integer" />
<jaxb:javaType name="java.lang.Double" xmlType="xs:double" />
<jaxb:javaType name="java.lang.Boolean" xmlType="xs:boolean" />
<jaxb:javaType name="java.lang.Long" xmlType="xs:long" />
</jaxb:globalBindings>
</xs:appinfo> ...[/XML]

Und schliesslich noch das "bindings.xjb"-File:
[XML]<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="2.0">

<jaxb:bindings schemaLocation="general.xsd" node="/xsd:schema">
<jaxb:schemaBindings>
<jaxb:package name="com.abc.asdf.package" />
</jaxb:schemaBindings>
</jaxb:bindings>

...

</jaxb:bindings>
[/XML]

Ich wäre extrem froh, wenn mir jemand helfen könnte. Ich bin dankbar für jeden noch so kleinen Tipp!!!

-brookman
 
Zuletzt bearbeitet:

Wildcard

Top Contributor
JAXB ist derartig umständlich... :autsch:
Zu deinem Problem kann ich dir leider nicht weiterhelfen, aber wenn das bei dir im Bereich des Möglichen ist, würde ich vorschlagen statt JAXB EMF zu verwenden.
EMF ist unter anderem auch ein XML Binding Framework, aber wesentlich komfortabler und mächtiger als JAXB. Listener Support bekommst du dort auch frei Haus (eine elegantere Implementierung als PropertyChangeSupport).
Eclipse Modeling - EMF - Home
 

brookman

Neues Mitglied
Danke für den Tipp!
Leider ist EMF für meine Anwendung nicht wirklich geeignet und völlig übertrieben. Ausserdem bräuchte es wieder Tage fürs customizing (Bean-Super-Klasse, "get-getter" für boolean, etc).
Meine (extrem hässliche) Abhilfe ist nun ein "Skript", welches nach dem Generieren einfach die PropertyChangeListeners ersetzt/umstellt.
In Perl wärs ein 3-Zeiler, hier der Java-Code :)
Java:
public class ChangeListenerConverter {

   public ChangeListenerConverter(File dir) {

      try {
         new FileTraversal() {
            @Override
            public void onFile(final File f) {
               if (f.getAbsolutePath().endsWith(".java")) {
                  String fileContent = readFileAsString(f);

                  String regex = "\\((.*)\\s+value\\)\\s*\\{\\s*support\\.firePropertyChange\\(\"(.*)\".*;\\s*this.*\\s*}";
                  Pattern pattern = Pattern.compile(regex);
                  Matcher matcher = pattern.matcher(fileContent);

                  while (matcher.find()) {
                     String newContent = "(" + matcher.group(1) + " value) {\n        " + matcher.group(1) + " oldValue = this." + matcher.group(2) + ";\n        this." + matcher.group(2)
                           + " = value;\n        support.firePropertyChange(\"" + matcher.group(2) + "\", oldValue, value);\n    }";
                     fileContent = fileContent.replaceFirst(regex, newContent);
                  }

                  writeStringToFile(fileContent, f);
               }
            }
         }.traverse(dir);
      } catch (IOException ignored) {
         // NOP
      }

   }

   public static void main(String[] args) {
      new ChangeListenerConverter(new File(args[0]));
   }

   public class FileTraversal {
      public final void traverse(final File f) throws IOException {
         if (f.isDirectory()) {
            // onDirectory(f);
            for (File child : f.listFiles()) {
               traverse(child);
            }
            return;
         }
         onFile(f);
      }

      // public void onDirectory(final File d) {
      // }

      public void onFile(final File f) {
      }
   }

   public static String readFileAsString(File file) {
      byte[] buffer = new byte[(int) file.length()];
      BufferedInputStream f = null;
      try {
         f = new BufferedInputStream(new FileInputStream(file));
         f.read(buffer);
      } catch (IOException e) {
         return "";
      } finally {
         if (f != null) {
            try {
               f.close();
            } catch (IOException ignored) {
               // NOP
            }
         }
      }
      return new String(buffer);
   }

   public static void writeStringToFile(String string, File file) {
      BufferedOutputStream f = null;
      try {
         f = new BufferedOutputStream(new FileOutputStream(file));
         f.write(string.getBytes());
         f.flush();
         f.close();
      } catch (IOException e) {
      } finally {
         if (f != null) {
            try {
               f.close();
            } catch (IOException ignored) {
               // NOP
            }
         }
      }
   }
}

PS:
Das Programm ersetzt dieses Muster:
Java:
...(XXX value) {
        support.firePropertyChange("YYY", this.YYY, value);
        this.col = value;...
Durch dieses:
Java:
...(XXX value) {
        XXX oldValue = this.YYY;
        this.YYY = value;
        support.firePropertyChange("YYY", oldValue, value);...
 
Zuletzt bearbeitet:

mvitz

Top Contributor
Worin genau besteht eigentlich der Vorteil, wenn der listener erst nach dem setzen und nicht davor aufgerufen wird?
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
W jaxws jaxb wsdl Java-Klassen generieren und binding.xml verwenden XML & JSON 1
A JAXB: XMLMixed generieren XML & JSON 0
B aus xsd Java Klassen generieren XML & JSON 3
N Java Code aus XML Datei generieren XML & JSON 8
M XML File generieren XML & JSON 3
T Möchte JSP Code in Attribut eines HTML Tags hinein generieren XML & JSON 3
S JAXB 2 und Java Annotationen/Interfaces generieren XML & JSON 3
G jaxb Vector (oder ähnliches) von Elementen generieren XML & JSON 6
T Klassen aus XML-Schema generieren und füllen XML & JSON 10
Y Welchen XML Parser / Klassen aus XSD generieren lassen XML & JSON 4
M Wie kann ich aus ein Document-Tree ein PDF generieren XML & JSON 2
A XML Dokument aus einem Schema ableiten/generieren? XML & JSON 6
S links aus xml generieren XML & JSON 13
8u3631984 jaxb XML Mapper - Root Element mit Attribut XML & JSON 20
Rakshan Unmarshalling multiple namespaces with jaxb XML & JSON 0
B JAXB und HTML XML & JSON 1
E JAXB und java.nio.file.Path XML & JSON 4
W jaxb-api XML Feld nicht gesendet setzt das Defaultvalue nicht XML & JSON 3
S Muss ich bei JAXB immer noch eine zusaetzliche List-Wrapper Klasse erstellen wenn ich mehrere Objekte serialisieren will..? XML & JSON 1
S JAXB mit mehreren zusammenhängenden .xsd-Files XML & JSON 0
N JAXB: Überflüssiges Wrapper-Tag für Map-Einträge XML & JSON 0
D JAXB mit Map und Color XML & JSON 2
K JAXB-XML unvollständig XML & JSON 1
K JAXB Unmarshelling XML & JSON 1
E JAXB und abstrakte Klasse(n) XML & JSON 0
B JAXB - Unmarshal -> Kinder bekommen und die Kinder von den Kinder XML & JSON 7
B JAXB - Marshal ArrayList XML & JSON 2
B JAXB - java.util.Locale does not have a no-arg default constructor XML & JSON 2
B JAXB-Fehler bei REST-Api XML & JSON 0
M JAXB HashMap Dynamisches Laden XML & JSON 0
M JAXB @XMLID und @XMLIDREF, wie Daten hinzufügen XML & JSON 2
P JAXB-Problem XML & JSON 1
R [JAXB] XmlRootElement und XmlType gemeinsam nutzen XML & JSON 0
I XML to Object - Mapping mit JAXB 1.0 XML & JSON 1
L JAXB - Generischen Wert mit Liste belegen XML & JSON 1
M XML-Datei mit JAXB und 2 Namespaces XML & JSON 0
K JAXB Annotation @XMLRootElement vererben XML & JSON 0
F JAXB Unmarshal - Kein "default Constructor" XML & JSON 2
F.S.WhiTeY JAXB: Schema nicht "erben" XML & JSON 2
B JAXB - manuell Klassen aus xsd XML & JSON 3
S Jaxb Unmarshalling Problem XML & JSON 4
S JAXB - Any Elementliste - wie Werte verändern? XML & JSON 4
R JAXB: A cycle is detected in the object graph. This will cause infinitely deep XML XML & JSON 6
M JAXB versucht abstrakte Klasse zu erzeugen XML & JSON 7
M JAXB: automatisches Groß schreiben Property XML & JSON 9
C Projekt - JAXB, EMF oder doch DOM? XML & JSON 4
C JAXB: XML-Elemente einlesen und als XML-Attribute ausgeben XML & JSON 7
R sax, stax, jdom, jaxb? List von Objekten speichern und laden XML & JSON 6
J JAXB: Mehrmals abspeichern XML & JSON 3
D XML Einlesen mit JaxB XML & JSON 4
W JAXB Binding customization XML & JSON 4
L JAXB und Interfaces XML & JSON 4
S Problem with JAXB unmarshalling classes that have the same name in @XmlRootElement XML & JSON 2
eykarhorn JAXB namespace attribut aus rootelement entfernen XML & JSON 2
nrg JAXB - nor any of its super class is known to this context XML & JSON 3
S aus XML mit JAXB zu Baumstruktur XML & JSON 3
nrg JAXB generell auf XMLs übertragbar XML & JSON 22
Landei JAXB: Wert von übergeordneten Element XML & JSON 4
G JAXB und verschachtelte Elemente? XML & JSON 6
G JAXB XML-Attribute feststellen XML & JSON 4
S JAXB 2 und JSR 303 XML & JSON 11
M [JAXB] @XmlAnyElement namespace XML & JSON 4
R JAXB Unmarshal XML & JSON 2
J JAXB und ArrayList XML & JSON 4
Landei Jpa2 -> jaxb??? XML & JSON 9
M JAXB - HashMap XML & JSON 1
dzim JAXB-Unmarshalling ignoriert/löscht Einträge aus XML - oder lässt sie verschwinden XML & JSON 3
ruutaiokwu jaxb eclipse plugin... XML & JSON 3
K JAXB: Klassen mit Annotation Lesen/Schreiben XML XML & JSON 3
R JAXB ausgewählte Felder XML & JSON 10
TiME-SPLiNTER JAXB: com.sun.xml.bind.v2.ContextFactory XML & JSON 3
V JAXB und leere Listen XML & JSON 2
L compareto(), equals() in JAXB generierten Dateien XML & JSON 3
D jaxb validierung/verification vor marshalling XML & JSON 3
J JAXB mit GregorianCalendar XML & JSON 4
HombreDelMundo JAXB can't handle interfaces XML & JSON 4
N Individuelles Wrapper-Element um Collection mit JAXB XML & JSON 6
B JAXB Unmarshalling mehrerer Objekte XML & JSON 2
V JAXB schema 2 java XML & JSON 3
B JPA + JAXB Mapping Problem XML & JSON 2
S Navigieren in unbekannten JAXB-Objecten XML & JSON 2
J JAXB NullPointerException im ContextFinder XML & JSON 6
H JAXB und STAX XML & JSON 2
H JAXB Probleme beim Unmarshalling XML & JSON 3
C Serialisierung mit JAXB XML & JSON 6
K JAXB und Maps -> Marshalling-Problem XML & JSON 6
S JAXB und viele verschachtelte Attribute XML & JSON 1
J JAXB - Map XML & JSON 2
O JAXB generierte Klassen sollen Serializable implementieren XML & JSON 1
aze JaxB: Nullelemente in Array nicht anzeigen XML & JSON 3
turmaline JAXB can't handle interfaces XML & JSON 20
sambalmueslie JAXB - Unmarshall ein XML-Document das aus zwei XSD Definitionen besteht XML & JSON 8
S JAXB und abstrakte Klasse(n) XML & JSON 4
P JAXB: Marshalling XML & JSON 7
aze JaxB Elemente in LinkedHashSet werden nicht wiededergegeben XML & JSON 3
M JAXB: Wie folgendes Konstrukt abbilden? XML & JSON 20
A Jaxb und Interfaces XML & JSON 12
B JaxB und XSD :-) XML & JSON 8
G JAXB - Marshaller - kein Rückgabewert XML & JSON 2
N XML will nicht weder JAXB noch XStream XML & JSON 8

Ähnliche Java Themen

Neue Themen


Oben