Docker + Netbeans + Liferay

Für eine einfache Integration von Docker für die Entwicklung nutze ich Netbeans IDE in Version 8. Die integrierte Docker Unterstützung vereinfacht es, neue Application Server aufzusetzen und für spätere Anwendungen zu verteilen.

Im Vorfeld muss die lokale Docker Installation angepasst werden. Standardmäßig hört Docker auf keinen TCP Socket, das muss customized werden.

Core OS gibt eine einfache Anleitung hierfür vor:

Customizing docker

The Docker systemd unit can be customized by overriding the unit that ships with the default Container Linux settings. Common use-cases for doing this are covered below.

Enable the remote API on a new socket

Create a file called /etc/systemd/system/docker-tcp.socket to make Docker available on a TCP socket on port 2375.

<code><span class="nn">[Unit]</span>
<span class="py">Description</span><span class="p">=</span><span class="s">Docker Socket for the API</span>

<span class="nn">[Socket]</span>
<span class="py">ListenStream</span><span class="p">=</span><span class="s">2375</span>
<span class="py">BindIPv6Only</span><span class="p">=</span><span class="s">both</span>
<span class="py">Service</span><span class="p">=</span><span class="s">docker.service</span>

<span class="nn">[Install]</span>
<span class="py">WantedBy</span><span class="p">=</span><span class="s">sockets.target</span>
</code>

Then enable this new socket:

<code>systemctl <span class="nb">enable </span>docker-tcp.socket
systemctl stop docker
systemctl start docker-tcp.socket
systemctl start docker
</code>

Test that it’s working:

<code>docker -H tcp://127.0.0.1:2375 ps</code>

Quelle: https://coreos.com/os/docs/latest/customizing-docker.html

Netbeans einrichten

Über den Reiter: Services -> Docker könnt ihr mit einem Rechtsklick eine neue Docker Instanz hinzufügen. Hierbei wäre es möglich sogar Remote Systeme anzuschließen, für Teams die auf einer zentralen Installation arbeiten.

Durch die vorhergehende Konfiguration von Docker sollte Successfull beim Test Connection erscheinen.

Docker + Liferay Image

Ich verwende aktuell noch ein Liferay 6.2 Image im Docker Umfeld für ein Projekt.

Daher habe ich auf das bereits erstelle Image von snasello zurück gegriffen.

Das könnt ihr hier https://hub.docker.com/r/snasello/liferay-6.2/

für eure Docker Installation herunterladen.

Liferay in Netbeans

Alle Docker Container werden anschließend im Netbeans gelistet. Ihr könnt den Liferay Container via Rechtsklick „run“ starten. Anschließend wird der Name definiert und das Port- Mapping.

Nachdem ihr „finish“ geklickt habt, wir der Container gestartet. In eurer Console erhaltet ihr dementsprechend den output.

How To Deploy Packages on Liferay Docker Container!

Um Portlets, Themes und Co auf dem Docker Container zu deployen, muss das deployment Verzeichnis lokal gemappt werden. Hierbei könnt ihr folgenden Befehl verwenden:

Laut Docker Dokumentation soll das über den Parameter -v möglich sein.

Quelle: https://docs.docker.com/engine/tutorials/dockervolumes/

Sobald es funktioniert, update ich den Beitrag!

Connect to Docker via Shell

Um den Docker Container zu konfigurieren oder Installationen / Konfigurationen vorzunehmen könnt ihr direkt via Shell auf das System zugreifen.

<code><span class="pln">sudo docker exec </span><span class="pun">-</span><span class="pln">i </span><span class="pun">-</span><span class="pln">t {name-of-docker-container} </span><span class="pun">/</span><span class="pln">bin</span><span class="pun">/</span><span class="pln">bash</span></code>

camunda cdi and multiple datasources

Ich durfte mich die letzten Tage mit einem ziemlich fiesen Fehler rum ärgern.

Wir optimieren unsere Bestellungen und vor allem automatisieren wir unseren gesamten Verarbeitungsprozess mit dem Backend.

Der gesamte Bestand und Bestellverfahren wird automatisch mit dem Shop, dem Backend und dem Versender abgeglichen.

Der Prozess zur Bestellübergabe wurde in camunda definiert. Die Service Tasks greifen auf CDI Beans zu. Diese Beans greifen auf JPA Ressourcen zurück.

Es wurden Projektbedingt 2 Resourceprojekte mit verschiedenen JTA- Resources definiert, die aber aufgrund der Architektur auf die gleiche Datenbank zugreifen.

 

Durch die schnelle Verarbeitung des Prozesses kommt  der Application Server durcheinander und Crasht bei der Verarbeitung der Transaktionen.  Einer der Ressourcenmanager lockt die Tabelle und verhindert das weitere verarbeiten der Daten.

Leider ist es mir nicht gelungen eine andere Lösung zu finden als beiden JPA Projekten der gleichen JNDI- Resource zu geben.  🙁

Jemand noch eine andere Idee?

JEE + Microservices, ein neuer IT- Kosmus

Wie man des öfteren ließt werden Micro-Services so etwas wie das nächste größere Ding sein für Moderne IT- Infrastruktur. Weg von großen Anwendungen die viele Daten zentralisiert speichern und nur im eigenen Universum zur Verfügung stellen. Es werden immer mehr Artikel über Micro-Services veröffentlicht. Kleine Datenmengen die sehr schnell zur Verfügung gestellt werden können. Dabei wird die Infrastruktur ziemlich zerrissen – und meiner Meinung nach – eine Art gewollte Unübersichtlichkeit geschaffen.

Da ich mich stetig mit der Entwicklung im JEE Umfeld beschäftige und eigentlich nur über Podcasts, Tutorials und Do-It-Yourself Lerne und meinen Wissensstand erweitere finde ich es nur fair, euch das leben an dieser Stelle etwas einfacher zu machen 😉

Im JEE7 Umfeld und der Verbindung von CDI- Beans ist es sehr einfach JAX-RS Web- Services zu erstellen. Ich werde die Tage ein Tutorial schreiben um euch zeigen zu können, wie einfach man die Kombination von

  • Maven
  • JEE7
  • JAX-RS

funktioniert.

Bis dahin.

PayOne + JEE Application

PayOne ist ziemlich umständlich zu integrieren. Für einen der großen Zahlungsdienstleister haben die Macher von PayOne ganz schön was nachzuholen. Ich persönliche finde PayOne vom Aufbau her ziemlich altmodisch. Man merkt, das dass Webportal des Zahlungsdienstleisters schon etwas in die Jahre gekommen ist. Ebenso der Komfort für die Kunden. Einen großen Pluspunkt hat PayOne. Die Integration in bestehende Systeme. Siehe magento – commerce, shopware, oxid, demandware oder intershop. Dadurch das sie in zahlreichen Großen Unternehmen zum Bestand zählen bietet eine feste Kundenbasis ein regelmäßigen Zahlungsfluss.

Wir sind gerade dabei die Schnittstellen für eine JEE- Anwendung anzubinden. Leider ist mir keine fertige Library im Netz über die Füße gefallen die ich nutzen hätte können. Somit kann ich wieder von vorne anfangen.

PayOne bietet seit einiger Zeit eine „Frontend“ – Lösung an. Hierbei wird über eine dynamische URL ein iFrame inkludiert oder die Seite aufgerufen über der die Zahlung abgewickelt werden kann. Dabei sind mir, im Gegensatz zur Konkurrenz z.B. Adyen wieder einige Nachteile aufgefallen.

  • Es kann lediglich eine Zahlungsart angeboten werden.
  • Die Implementierung ist ziemlich aufwendig da sehr genau Reihenfolgen eingehalten werden müssen.
  • Standard für die Implementierung ist PHP.
  • Relativ langsame Abwicklung des Zahlungsprozesses.

Ich hatte die letze Zeit öfters Gelegenheit einige der Zahlungsdienstleister ausprobieren zu können. Deren Schnittstellen zu testen und wie man darauf reagieren kann. Mir ist aufgefallen das Adyen an dieser Stelle sehr stark ist und mit einfachsten Mechanismen gute Zahlungsmöglichkeiten anbietet.

Unsere Entscheidung ist etwas ungewöhnlich. Wir haben uns trotz der Nachteile für PayOne entschieden. Folgende Gründe haben dafür gesprochen:

  • Unser Sachbearbeiter war stets bemüht alle Informationen die nötig waren zu bekommen
  • Kooperativ mit uns zusammen zu arbeiten
  • Gebühren und Kosten zu minimieren, so das wir als StartUp ebenfalls eine Chance haben
  • Schnelle Reaktion bei Support-Anfragen
  • Unterstützung beim Implementierungsaufwand

Trotz der gestiegenen Aufwände bei der Implementierung sollte es möglich sein in kurzer Zeit eine kleine Library für euch zur Verfügung stellen zu können die die Zahlungsabwicklung mit dem Frontend-Interface abzubilden.

 

Bis dahin

Euer Johannes

WildFly HttpServlet Alternative zu glassfish alternatedocroot_1

Glassfish bietet die Möglichkeit einfach und schnell neue Ordner ins System einzubinden und diese per URL- Pattern anzusprechen.

Die Parameter werden in der: glassfish-web.xml angegeben. Für mehr Details können sie gerne bei Oracle in die Details gehen.

&lt;property name="alternatedocroot_1" value="from=/my.jpg dir=/srv/images/jpg"/&gt;
&lt;property name="alternatedocroot_2" value="from=*.jpg dir=/srv/images/jpg"/&gt;
&lt;property name="alternatedocroot_3" value="from=/jpg/* dir=/src/images"/&gt;

Leider unterstützt jboss seit einigen Versionen eine ähnliche Funktion nicht mehr. Dafür kann per HttpServlet ein Ordner eingebunden werden der ebenfalls per Pattern angesprochen wird.

package de.kuw.jee.kuwbid.servlet;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLDecoder;

import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import de.kuw.jee.core.ejb.ParameterBean;
import de.kuw.jee.kuwbid.mb.ApplicationBean;

@WebServlet(urlPatterns = "/images/*", initParams = { 
		@WebInitParam(name = "basePath", value = "/home/jskoeber/server/wildfly/uploads/documents") }
)
public class ImageServlet extends HttpServlet {
	private static final long serialVersionUID = -3522881745170031638L;
	private String basePath = "";
	
	@Inject
	private ApplicationBean app;
	
	@Inject
	private ParameterBean parameter;
    
    public void init() throws ServletException {
        this.basePath = getInitParameter("basePath");
        
        if(!parameter.getParameter("uri.images", app.getMandant()).getWert().isEmpty()) {
        	basePath = parameter.getParameter("uri.images", app.getMandant()).getWert(); 
        }
        
        // Validate base path.
        if (this.basePath == null) {
            throw new ServletException("FileServlet init param 'basePath' is required.");
        } else {
            File path = new File(this.basePath);
            if (!path.exists()) {
                throw new ServletException("FileServlet init param 'basePath' value '" + this.basePath + "' does actually not exist in file system.");
            } else if (!path.isDirectory()) {
                throw new ServletException("FileServlet init param 'basePath' value '" + this.basePath + "' is actually not a directory in file system.");
            } else if (!path.canRead()) {
                throw new ServletException("FileServlet init param 'basePath' value '" + this.basePath + "' is actually not readable in file system.");
            }
        }
    }
    

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String requestedFile = request.getPathInfo();
		
		File file = new File(basePath, URLDecoder.decode(requestedFile, "UTF-8"));
		if (!file.exists()) {
            // Throw 404, redirect to error page may is another selection
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
		
		// write via response's OutputStream
		FileInputStream inputStream = null;

		try {
			inputStream = new FileInputStream(file);
			byte[] buffer = new byte[1024];
			int bytesRead = 0;

			do {
				bytesRead = inputStream.read(buffer, 0, buffer.length);
				response.getOutputStream().write(buffer, 0, bytesRead);
			} while (bytesRead == buffer.length);

			response.getOutputStream().flush();
		} finally {
			if (inputStream != null)
				inputStream.close();
		}
	}
}

Primefaces 5 SelectOneMenu + Hibernate + Wildfly and Entities

Die letzten zwei Tage waren wieder eine Suche nach dem richtigen Weg. Im Normalfall würde sich mein JPA Manager um eine performante Art und Weise kümmern meine Daten zwischen zu lagern oder neu zu laden. Hibernate geht leider eine etwas andere Logik vor und cached nicht lange genug die Entities vor. Das heißt bei einem Neuaufruf über eine andere Bean wird nicht vom Application Server geladene Inhalte übertragen sondern die Abfrage erneut gestartet. Somit wäre ein flushen im Entity Manager nach dem updaten von Inhalten nur optional.

Es ist ziemlich einfach wenn man weiß woran es liegt. Und zwar wird bei Entities eine equals Methode geladen z.b.

package de.kuw.jee.core.verwaltung;

import java.io.Serializable;

import javax.persistence.*;

import java.util.List;
import java.util.logging.Logger;


/**
 * The persistent class for the virtual_domains database table.
 * 
 */
@Entity
@Table(name="virtual_domains")
@NamedQuery(name="VirtualDomain.findAll", query="SELECT v FROM VirtualDomain v")
public class VirtualDomain implements Serializable {
	private static final long serialVersionUID = 1L;
	private static final Logger log = Logger.getLogger(VirtualDomain.class.getName());

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private int id;

	private boolean active;

	private boolean deleted;

	private String directory;

	@Column(name="domain_type")
	private String domainType;

	private String name;

	//bi-directional many-to-one association to SysDomain
	@OneToMany(mappedBy="virtualDomain")
	private List sysDomains;

	//bi-directional many-to-one association to VirtualAlias
	@OneToMany(mappedBy="virtualDomain")
	private List virtualAliases;

	//bi-directional many-to-one association to BillCustomer
	@ManyToOne
	@JoinColumn(name="customer_id")
	private BillCustomer billCustomer;

	//bi-directional many-to-one association to VirtualUser
	@OneToMany(mappedBy="virtualDomain")
	private List virtualUsers;

	public VirtualDomain() {
	}

	public int getId() {
		return this.id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public boolean getActive() {
		return this.active;
	}

	public void setActive(boolean active) {
		this.active = active;
	}

	public boolean getDeleted() {
		return this.deleted;
	}

	public void setDeleted(boolean deleted) {
		this.deleted = deleted;
	}

	public String getDirectory() {
		return this.directory;
	}

	public void setDirectory(String directory) {
		this.directory = directory;
	}

	public String getDomainType() {
		return this.domainType;
	}

	public void setDomainType(String domainType) {
		this.domainType = domainType;
	}

	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public List getSysDomains() {
		return this.sysDomains;
	}

	public void setSysDomains(List sysDomains) {
		this.sysDomains = sysDomains;
	}

	public SysDomain addSysDomain(SysDomain sysDomain) {
		getSysDomains().add(sysDomain);
		sysDomain.setVirtualDomain(this);

		return sysDomain;
	}

	public SysDomain removeSysDomain(SysDomain sysDomain) {
		getSysDomains().remove(sysDomain);
		sysDomain.setVirtualDomain(null);

		return sysDomain;
	}

	public List getVirtualAliases() {
		return this.virtualAliases;
	}

	public void setVirtualAliases(List virtualAliases) {
		this.virtualAliases = virtualAliases;
	}

	public VirtualAlias addVirtualAlias(VirtualAlias virtualAlias) {
		getVirtualAliases().add(virtualAlias);
		virtualAlias.setVirtualDomain(this);

		return virtualAlias;
	}

	public VirtualAlias removeVirtualAlias(VirtualAlias virtualAlias) {
		getVirtualAliases().remove(virtualAlias);
		virtualAlias.setVirtualDomain(null);

		return virtualAlias;
	}

	public BillCustomer getBillCustomer() {
		return this.billCustomer;
	}

	public void setBillCustomer(BillCustomer billCustomer) {
		this.billCustomer = billCustomer;
	}

	public List getVirtualUsers() {
		return this.virtualUsers;
	}

	public void setVirtualUsers(List virtualUsers) {
		this.virtualUsers = virtualUsers;
	}

	public VirtualUser addVirtualUser(VirtualUser virtualUser) {
		getVirtualUsers().add(virtualUser);
		virtualUser.setVirtualDomain(this);

		return virtualUser;
	}

	public VirtualUser removeVirtualUser(VirtualUser virtualUser) {
		getVirtualUsers().remove(virtualUser);
		virtualUser.setVirtualDomain(null);

		return virtualUser;
	}

	@Override
	public boolean equals(Object obj) {
		if(obj != null) {
			log.info("Equals action in VirtualDomain for obj: " 
					 + obj.toString());
		}
		return super.equals(obj);
	}
}

Zum testen habe ich die equals Methode rausgezogen um zu sehen was geprüft wird im selectOneMenu von Primefaces. Und wie ich es mir gedacht habe. Wildfly weiß nicht mehr das die Daten in der view schon existieren und werden daher nochmal aus der DB geladen und somit natürlich einen anderen Hash zugeordnet. Um diesen Fehler des: „value not valid“ zu vermeiden müsst ihr die Bean die ViewScoped per CDI Injected wird die Wertetabelle rausziehen z.B.


Der Primefaces

package de.kuw.jee.verwaltung.converter;

import java.util.logging.Logger;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import javax.inject.Inject;

import de.kuw.jee.core.verwaltung.VirtualDomain;
import de.kuw.jee.verwaltung.mb.DomainBean;

@FacesConverter("domainConverter")
public class DomainConverter implements Converter {
	private Logger log = Logger.getLogger(DomainConverter.class.getName());
	
	@Inject
	private DomainBean domainBean;
	
	private int id;
	
	@Override
	public Object getAsObject(FacesContext context, UIComponent component, String value) {
		VirtualDomain dom = null;
        id = Integer.valueOf(value);
        if(value != null &amp;&amp; id &gt; 0) {
        	for(VirtualDomain tmp : domainBean.getDomains()) {
        		if(tmp.getId() == id) {
        			dom = tmp;
        		}
        	}
        	
        	log.info("Object is: " + dom.toString() );
        }
        
        return dom;
    }

	@Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
    	String returnVal = "";
    	if(value instanceof VirtualDomain) {
    		 VirtualDomain dom = (VirtualDomain) value;
    		 returnVal = String.valueOf(dom.getId());
    	} else {
    		returnVal = "";
    	}
    	log.finest("GetAsString is: " + returnVal);
        return returnVal;
    }
}

Sobald ihr das beachtet, und aus bestehenden Datasets lest, werdet ihr den Fehler der falschen Hashed und equals Fehler nicht mehr bekommen.

viel Spaß beim ausprobieren.

osRetail – Primefaces 4 Upgrade

Wir sind wieder einen Schritt weiter. osRetail in der finalen Primefaces 4.0 Version. Und als Maven Projekt. osRetail das erste open Source ERP System für den Handel. Wir versuchen das starre Korsett eines fertigen ERP System aufzubrechen. Dem Kunden eine möglichst große Vielfalt an Standardfunktionalität zu bieten und auch kostspielige Funktionen wie der Katalogerstellung frei Haus mitzuliefern.

Vor ca. einem Jahr haben wir uns dazu entschlossen ein großes Refactoring der Software durchzuführen. So haben wir nicht nur die Entwicklungsumgebung von Netbeans auf Eclipse geändert. Wir haben auch IceFaces ausgetauscht und – mit dem leistungsstarken Framework – Primefaces einen weiteren Schritt zu einer moderneren Arbeitoberfläche geebnet.

jee7-standard

Ebenso wurde der Code überarbeitet. Derzeit verwenden wir den JEE7 Standard um den aktuellsten Stand der Enterprise Entwicklung von Java nutzen zu können. Autodeployments über Jenkins erleichtern uns die Arbeit erheblich da wir alle Code Commits und Änderungen auf den Testsystem schnellst möglich dem publishen können.

maven-overview-plugin

Maven unterstützt uns bei der Library Auswahl. Mit einfachsten Mitteln ist es möglich neue oder ältere Bibliotheken auszuwählen und automatisch in der Entwicklung und beim Deployment zu verwenden.

Glassfish 4 bietet uns einen schnellen Application- Server der leicht zu handeln ist. Skalierbarkeit, effizientes Arbeiten und schnelle Deployments standen dabei im Vordergrund. Durch einfache Erweiterbarkeit ist es uns möglich schnell auf Kundenwünsche zu reagieren.

Maven- Aufbau eines JEE Projekts

Automatisches Deployment ist so eine Herausforderung die man nicht einfach mal so nebenher macht. Allgemein gesehen geht es recht fix wenn man mal verstanden hat wie alles funktioniert.

Zum einen wird ein funktionsfähiges Maven Projektgruppe benötigt. Das heißt eine JEE Anwendung mit ihren Komponenten:

  • JPA
  • EJB
  • Web
  • EAR

Container. Das Ganze mit vernünftigen pom.xml Files die auch richtig funktionieren.

POM.XML für  JPA Projekt.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.kuw.example</groupId>
  <artifactId>ExampleJPA</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>ExampleJPA</name>
  <description>Java Persistence for Example</description>
  <build>
    <sourceDirectory>src</sourceDirectory>
    <resources>
      <resource>
        <directory>src</directory>
        <excludes>
          <exclude>**/*.java</exclude>
        </excludes>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.0</version>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <dependencies>
    <dependency>
		<groupId>org.eclipse.persistence</groupId>
		<artifactId>eclipselink</artifactId>
		<version>2.5.0</version>
	</dependency>
  </dependencies>
</project>

POM.XML für EJB Projekt:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.kuw.example</groupId>
  <artifactId>ExampleEJB</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>ejb</packaging>
  <build>
    <sourceDirectory>ejbModule</sourceDirectory>
    <resources>
      <resource>
        <directory>ejbModule</directory>
        <excludes>
          <exclude>**/*.java</exclude>
        </excludes>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.0</version>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-ejb-plugin</artifactId>
        <version>2.3</version>
        <configuration>
          <ejbVersion>3.1</ejbVersion>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <dependencies>
  	<dependency>
	 	<groupId>com.kuw.example</groupId>
		<artifactId>ExampleJPA</artifactId>
		<version>${project.version}</version>
		<scope>provided</scope>
		<type>jar</type>
	</dependency>   
	<dependency>
		<groupId>javax.mail</groupId>
		<artifactId>mail</artifactId>
		<version>1.4.7</version>
	</dependency>
	<dependency>
		<groupId>org.apache.commons</groupId>
	  	<artifactId>commons-lang3</artifactId>
	  	<version>3.1</version>
	</dependency>
	<dependency>
		<groupId>org.eclipse.persistence</groupId>
		<artifactId>eclipselink</artifactId>
		<version>2.5.0</version>
	</dependency>
	<dependency>
		<groupId>javax.ejb</groupId>
		<artifactId>javax.ejb-api</artifactId>
		<version>3.2</version>
	</dependency>
  </dependencies>
  <name>QuatEJB</name>
</project>

POM.XML für Web Projekt inkl. Primefaces

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.kuw.example</groupId>
  <artifactId>Example</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  <name>Quat</name>
  <build>
    <sourceDirectory>src</sourceDirectory>
    <resources>
      <resource>
        <directory>src</directory>
        <excludes>
          <exclude>**/*.java</exclude>
        </excludes>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.0</version>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.3</version>
        <configuration>
          <warSourceDirectory>WebContent</warSourceDirectory>
          <failOnMissingWebXml>false</failOnMissingWebXml>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <dependencies>
	  <dependency>
		<groupId>javax.faces</groupId>
		<artifactId>jsf-api</artifactId>
		<version>2.1</version>
	</dependency>
  	<dependency>
  		<groupId>org.apache.directory.studio</groupId>
  		<artifactId>org.apache.commons.io</artifactId>
  		<version>2.4</version>
  	</dependency>
  	<dependency>
		<groupId>commons-fileupload</groupId>
		<artifactId>commons-fileupload</artifactId>
		<version>1.3</version>
	</dependency>
	<dependency>
	 	<groupId>com.kuw.example</groupId>
		<artifactId>ExampleEJB</artifactId>
		<version>0.0.1-SNAPSHOT</version>
		<scope>provided</scope>
		<type>ejb</type>
	</dependency>
	<dependency>
	 	<groupId>com.kuw.example</groupId>
		<artifactId>ExampleJPA</artifactId>
		<version>0.0.1-SNAPSHOT</version>
		<scope>provided</scope>
		<type>jar</type>
	</dependency>
  	<dependency>
		<groupId>org.primefaces.extensions</groupId>
		<artifactId>primefaces-extensions</artifactId>
		<version>0.7.1</version>
	</dependency>
   <dependency>
		<groupId>org.primefaces.extensions</groupId>
		<artifactId>resources-ckeditor</artifactId>
		<version>0.7.1</version>
	</dependency>
	<dependency>
		<groupId>org.primefaces.extensions</groupId>
		<artifactId>resources-codemirror</artifactId>
		<version>0.7.1</version>
	</dependency>
		<dependency>
		<groupId>org.primefaces.extensions</groupId>
		<artifactId>all-themes</artifactId>
		<version>1.0.8</version>
	</dependency>
    <dependency>  
	    <groupId>org.primefaces</groupId>  
	    <artifactId>primefaces</artifactId>  
	    <version>3.5</version>  
	</dependency>                                 
  </dependencies>
  <repositories>
	<repository>  
	    <id>prime-repo</id>  
	    <name>PrimeFaces Maven Repository</name>  
	    <url>http://repository.primefaces.org</url>  
	    <layout>default</layout>  
	</repository>  
  </repositories>
</project>

POM.XML für EAR.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.kuw.example</groupId>
  <artifactId>ExampleEAR</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>ear</packaging>
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-ear-plugin</artifactId>
        <version>2.8</version>
        <configuration>
          <earSourceDirectory>EarContent</earSourceDirectory>
          <generateApplicationXml>false</generateApplicationXml>
          <version>6</version>
          <defaultLibBundleDir>lib</defaultLibBundleDir>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <name>ExampleEAR</name>
  <url>www.ka-und-we.de</url>
  <dependencies>
  	<dependency>
  		<groupId>com.kuw.example</groupId>
  		<artifactId>ExampleEJB</artifactId>
  		<version>${project.version}</version>
  		<type>ejb</type>
  	</dependency>
  	<dependency>
  		<groupId>com.kuw.example</groupId>
  		<artifactId>QsMPrime</artifactId>
  		<version>${project.version}</version>
  		<type>war</type>
  	</dependency>
  	<dependency>
  		<groupId>com.kuw.example</groupId>
  		<artifactId>ExampleJPA</artifactId>
  		<version>${project.version}</version>
  		<type>war</type>
  	</dependency>
  </dependencies>
</project>

JEE Anwendung: QUAT

Es ist ein attraktives Entwicklungsumfeld im JEE Bereich. Webapplications mit EJB3 Anbindung und Managed- Beans.

Im Standard JEE6 wurde viel Aufmerksamkeit auf Annotations gelenkt und die vereinfachte Kommunikations der Beans mit dem Frontend. Der neue JEE7 Standard, erst ein paar Wochen alt wird jetzt speziell die Ausrichtung im Bereich Ajax im Blick haben. Light- Weight Communication mit dem Backend wenn man so will. Wenige Daten die geliefert werden und somit die Performance von Applikationen beschleunigt.

Ich werde euch hier ein kleines Beispiel für eine JEE Anwendung erstellen inkl. der aktuellen Version von Eclipse Kepler und Glassfish 4.

Die JEE Anwendung wird mit dem Plugin von Primefaces 3.5 laufen. Einem leistungsstarken Ajax- Framework das basierend auf jQuery UI viel interaktive Bearbeitungsmöglichkeiten bietet.

Nachteil von Primefaces. Die jQuery UI hat, meines erachtens nicht gerade ein business orientiertes Interfaces Design. Die Buttons und Eingabemasken wirken sehr groß und für ein schlankeres Aussehen müssen einige CSS Classes überarbeitet werden.

Auch muss man sich vor Augen führen das durch den zusätzlichen CSS und Javascript Aufwand die einzelnen Seiten etwas Content- lastiger werden und somit die Ladezeit im Gegensatz zu reinem JSF2 länger sein können. Da man aber sehr viele Daten nachladen kann wird nur der Erstaufruf etwas länger benötigen. Sobald alle Daten Clientseitig gecached wurden wird die Performance deutlich besser sein.

Maven wird in diesem kleinen Projekt eine weiter Rolle spielen. Um möglichst einfach alle Komponenten bauen zu lassen ohne sich um die Libraries kümmern zu müssen oder die Libraries im SVN bereit zu stellen werde ich mich darum kümmern das das Projekt mit Maven gebaut werden kann.

Vorteile:

  • Versionierung des Projektes anhand von Maven- einstellungen.
  • Einfaches Updaten von Libraries
  • Schnelles Bauen von Projekten

Nachteil:

Langwieriges einstellen der Maven Poms um einen erfolgreichen Build zu generieren. Mittlerweile habe ich auch festgestellt das nicht alle POM Einstellungen Plattformunabhängig sind. Es kann sein das Builds teilweise unter Windows laufen und auf dem Mac Fehler verursachen weil Abhängigkeiten fehlen.

Projektname: QUAT

Das Projekt das ich seit längerem realisiere nennt sich QUAT. Mittlerweile stecken knappe 2 Jahre Entwicklung in dem System. Angefangen hat es mit einer einfachen PHP Anwendung die mittlerweile ihre Alter erreicht hat und dank unzähliger PHP Updates auch einiges an Funktionen nicht mehr unterstützen bzw. nur noch per Workaround laufen.

QUAT wird z.B. für ein Callcenter verwendet werden können das sich mit der Qualitätssicherung von Mitarbeiter beschäftigt. Überall wo die Leistung vom Mitarbeiter eine Bewertung benötigt und die Qualität in Gesprächen oder direkter Kommunikation am Telefon geprüft werden muss um den Erfolg der Firma zu steigern oder gezielt Schulungen für Mitarbeiter anzubieten.

Aber erstmal genug um den Nutzen der Software. Wir möchten uns die technische Seite etwas genauer ansehen und somit den Aufbau der Software.

[HIER WERDEN ALLE ZUKÜNFTIGEN ARTIKEL ZU QUAT GELISTET UND VERLINKT|

 

ManagedBean URL Parameter lesen

Vor kurzem musste ich mich fragen wie man ein paar einfache URL Parameter ausgelesen bekommt. Das ganze in der ManagedBean. Eigentlich ist die Lösung einfach wenn man einmal begriffen hat wozu ManagedProperties gedacht sind. Das schöne ist das es über eine einfach Annotation geht und in der faces-config.xml nur eine Kleinigkeit hinzugefügt werden muss.

In unserem fall ist es z.B. /faces/test/test.xhtml?test1=hurz&test2=gurz

 

<managed-bean>
    <managed-bean-name>bean</managed-bean-name>
    <managed-bean-class>com.example.Bean</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
    <managed-property>
        <property-name>test1</property-name>
        <value>#{param.test1}</value>
    </managed-property>
    <managed-property>
        <property-name>test2</property-name>
        <value>#{param.test2}</value>
    </managed-property>
</managed-bean>

Wichtig hierbei ist die Scope. Falls ihr die Scope auf Session belasst werdet ihr ein Instanziierungsproblem bekommen. Da der URL Aufruf wie der Name schon sagt ein einfacher und nur für den Moment geltender Aufruf ist ist der Scope ganz wichtig bei der Sache das auch die Parameter korrekt gelesen werden können. Somit achtet darauf das die Scope auf alle Fälle REQUEST enthält.

Anschließend könnt ihr in eurer ManagedProperty die zwei Parameter auslesen:

@ManagedProperty ("{test1}")
private String test1;
@ManagedProperty ("{test2}")
private String test2;

public void setTest1(String test1) {
 this.test1 = test1;
}
public void setTest2(String test2) {
 this.test2 = test2;
}