Arndt Schönbergs Weblog

Dienstag Feb 21, 2017

Spooky Exceptions (6) java.lang.NullPointerException - ....MergeManager.registerObjectForMergeCloneIntoWorkingCopy(MergeManager.java:1054)

Umgebung

  • Wildfly 10
  • EE7
  • Postgres
  • Eclipselink

Situation

Es kommt folgende NPE von Eclipselink:
 
1:10:10,476 INFO  [stdout] (default task-32) java.lang.NullPointerException
2017-02-20 11:10:10,485 INFO  [stdout] (default task-32)     at 
org.eclipse.persistence.internal.sessions.MergeManager.registerObjectForMergeCloneIntoWorkingCopy(
MergeManager.java:1054) 
~[eclipselink.jar!/:2.6.4.v20160829-44060b6]
2017-02-20 11:10:10,485 INFO  [stdout] (default task-32)     at 
org.eclipse.persistence.internal.sessions.MergeManager.mergeChangesOfCloneIntoWorkingCopy(
MergeManager.java:564) 
~[eclipselink.jar!/:2.6.4.v20160829-44060b6]
2017-02-20 11:10:10,485 INFO  [stdout] (default task-32)     at 
org.eclipse.persistence.internal.sessions.MergeManager.mergeChanges(MergeManager.java:313) 
Auch dies ist leider wieder eine Meldung, die die eigentlich Ursache verschleiert. Der Grund für diese NPE ist, dass eine Entität nicht in der persistence.xml angegeben wurde bzw. von einer automatischen Erkennung nicht registriert wurde.

Dienstag Feb 14, 2017

Spooky Exceptions (5) Caused by: org.postgresql.util.PSQLException: ERROR: column "date_start" is of type date but expression is of type character varying

Umgebung

  • Wildfly 10
  • EE7
  • Postgres
  • Eclipselink

Situation

Wenn wir versuchen ein abhängiges Objekt über Datenbankattribute vom Typ Date zu referenzieren (mindestens eines), kann dies zu Problemen führen. Wir haben folgende Abhängigkeit
 
    @JoinColumns({
        @JoinColumn(name = "mandator_id", referencedColumnName = "mandator_id", insertable = true, updatable = true),
        @JoinColumn(name = "date_start", referencedColumnName = "date_start", insertable = true, updatable = true)
    })
    @ManyToOne
    private AccountingPeriod accountingPeriodEnd = null;
Es wird also auf ein Objekt vom Typ AccountingPeriod verwiesen. Beide Attribute für die Verbindung sind schreibend definiert. Versucht man nun diesen Wert mit null zu persistieren, kann es zu folgender Fehler-Meldung kommen
 
Caused by: org.postgresql.util.PSQLException: ERROR: column "date_start" is of type date but expression is of type character varying
Innerhalb des Mappings erkennt die JPA nicht den korrekten Typ. Je nach Datenbank, kann dies zu Problemen führen.

Lösung

Es muss das Date-Attribut "ausgelagert" werden. Hierfür definieren wir
 
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "date_start")
    private Date dateEnd = null;

    @JoinColumns({
        @JoinColumn(name = "mandator_id", referencedColumnName = "mandator_id", insertable = true, updatable = true),
        @JoinColumn(name = "date_start", referencedColumnName = "date_start", insertable = false, updatable = false)
    })
    @ManyToOne
    private AccountingPeriod accountingPeriodEnd = null;
Im entsprechneden Setter müssen wir das korrekte Befüllen des Date-Attribits sicherstellen
 
    public AccountingPeriod getAccountingPeriodEnd() {
        return this.accountingPeriodEnd;
    }
    public void setAccountingPeriodEnd(AccountingPeriod value) {
        this.accountingPeriodEnd = value;
        if (value != null) {
            this.setDateEnd(value.getDateStart());
        } else {
            this.setDateEnd(null);
        }
    }

    protected Date getDateEnd() {
        return this.dateEnd;
    }
    private void setDateEnd(Date value) {
        this.dateEnd = value;
    }
Hierdurch ist der Typ eindeutig definiert und JPA hat keine Probleme mehr.

Donnerstag Feb 09, 2017

JSF Ressourcen in Libraries

Umgebung

  • Wildfly 10
  • EE7

Ressourcen können in JEE in Bibliotheken organisiert werden. Dabei bildet eine Bibliothek ein Unterverzeichnis in den Ressourcen-Verzeichnissen, die beim Start des Servers zusammengesucht werden. Hiermit können verschiedene interessante Punkte wie beispielsweise

  • Themes in JSF
  • Versionierungen der GUI
implementiert werden. Hier für müssen die Grafiken, CSS Dateien und andere Resosourcen in einem entsprechenden Verzeichnis unterhalb eines der verwendeten resources Verzeichnisse. Beispielsweise ein Verzeichnis mit dem Namen themeKunde1. In den JSF Seiten wird auf diese Dateien dann über das zusätzliche Tag library zugegriffen. Die Library ist hierbei lediglich eine Erweiterung des Pfades für den Zugrigff auf die Dateien.
  <h:outputStylesheet library="themeKunde1" name="css/login.css" />
Es wird also themeKunde1/css/login.css in den Ressourcen gesucht. Wichtig ist hierbei, dass keine führenden "/" in den Angaben enthalten sind. Wenn in einer Sessionbean ein entsprechendes Attribut verwaltet wird, kann über dieses die Bibliothek dynamisch geändert werden.
  <h:outputStylesheet library="#{sBTheme.themeWebLibrary}" name="css/login.css" />
Eine elegante und einfache Integration, die die Java Enterprise Umgebung hier bereitstellt.

Dienstag Nov 08, 2016

Tipp 01 Primefaces: Tabellen sortieren sich nicht

Umgebung

  • EE7
  • JSF 2.2
  • Primfaces 6 Snapshot
Folgender Fall ist gegeben: In einer xhtml-Seite wird auf eine Liste in einer Sessionbean für eine Tabelle verwiesen.
<p:dataTable value="#{sBDummy.myList}" var="item" >
	<p:column sortBy="#{item.description}" >
		<f:facet name="header" >
			<h:outputText value="Beschreibung" />
		</f:facet>
		<h:outputText value="#{item.description }" />
	</p:column>
</p:dataTable>
Es kommt zu Problemen bei der Sortierung der Spalten, wenn die Liste der Tabelle nicht in der Sessionbean verwaltet, sondern jedes mal aus einer Facade abgefragt wird. Die Anzeige der Tabelle verhält sich in diesem Fall normal, die Sortierung innerhalb des Kopfes der Tabelle funktioniert aber nicht.
@EJB
privat etransient MyDataFacade myDataFacade;

/** @return Angezeigte Liste */
public List getMyList () {
	// Die Daten werden aus der Facade z.B. aus der DB geladen
	return this.myDataFacade.findData();;
}
Es wird also die Liste bei jedem get Aufruf aus der EJB geladen. Dies kann zum einen ein Performanceproblem werden, da die get-Methode bei einem Server-Roundtrip mehrmals aufgerufen wird. Zum anderen funktioniert die Sortiereigenschaft der Tabelle bei Primefaces nicht. Um die Funktionalitäte zu gewährleisten, muss die Liste in der Sessionbean mit einem Attribut verwaltet werden. Die Initialisierung erfolgt je nach Bedarf
  • postconstuct-Methode
  • Navigation zu der xhtml-Seite
  • manuell durch Betätigung eines Buttons

Freitag Okt 14, 2016

Tipps zu JSF Composite Componentes

Umgebung

  • EE7
  • JSF 2.2
Mit diesem Post möchte ich einige Hinweise zu den Composite Componentes von JSF geben, die immer wieder gefragt werden.

Zugriff auf Attribute des Interfaces

Auf Attribute des Interfaces wird über #{cc.attrs.<Name aus dem Interface>} zugegriffen.

Rendered und id verhalten sich seltsam

Composite Componentes leiten sich aus UINamingContainer und UIComponentBase ab. Daher dürfen und sollen einige Attribute wie rendered oder id nicht überschrieben werden. Diese stehen bereits durch die Ableitung zur Verfügung und können direkt übergeben werden.

Parameter an action oder actionListener binden

Sollen Methoden für action oder actionListener übergeben werden, müssen im Interface die Signaturen angegeben werden z.B.
<cc:attribute name="action" required="true" method-signature="java.lang.String action()" />
<cc:attribute name="actionListener" required="true" method-signature="void actionListener(javax.faces.event.ActionEvent)" />
Werden diese Attribute in der Komponente an action oder actionListener von entsprechenden Komponenten (z.B. h:actionButton) gebunden, dürfen sie nicht leer sein. Es sollte also required="true" verwendet werden. Alternativ müssen in der Komponente verschiedene Varianten umgesetzt und über z.B. rendered=“not empty cc.attrs.action“ ein- und ausgeblendet werden.

Einbinden von Kindernkomponenten

Kindelemente aus den HTML-Seiten werden über <cc:insertChildren /> eingefügt.

Calendar

Feeds

Search

Links

Navigation