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.

<property name="alternatedocroot_1" value="from=/my.jpg dir=/srv/images/jpg"/>
<property name="alternatedocroot_2" value="from=*.jpg dir=/srv/images/jpg"/>
<property name="alternatedocroot_3" value="from=/jpg/* dir=/src/images"/>

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();
		}
	}
}

Varnish Cache für Webserver

Varnish Installieren

$ sudo apt-get install varnish

Varnish Konfigurieren

Die Standardkonfigurationen von Varnish findet ihr unter /etc/default/varnish und /etc/varnish/default.vcl

Für den Cache wird in der /etc/default/varnish ein daemon konfiguriert der nach der Installation per sudo bereits vorkonfiguriert ist. Ihr könnt zur Sicherheit noch einmal nachsehen.

DAEMON_OPTS="-a :6081  
             -T localhost:6082  
             -f /etc/varnish/default.vcl  
             -S /etc/varnish/secret  
             -s malloc,256m"

Der Port des daemon wird nach der Konfiguration von 6081 auf 80 geändert.

In der /etc/varnish/default.vcl wird der listener definiert auf den varnish hört.

backend default {
    .host = "127.0.0.1"; 
    .port = "80"; 
}

Für eine detailierte Information und ein paar Erklärunge könnt ihr gerne unter: Sitepoint – Getting Started with Varschnish nachsehen und auch diese Verweise weiterarbeiten.

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 && id > 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.

Citrix ICA Client / Receiver für Ubuntu

Für alle die ein Linux bzw. ein Ubuntu verwenden und den Citrix Receiver in der Version 13 installieren wollen. Ihr könnt diese Installationsanleitung:

https://help.ubuntu.com/community/CitrixICAClientHowTo

für alle nötigen Ubuntu Versionen benützen. Ebenso funktioniert die Anleitiung:

Citrix Receiver 13.0 on Ubuntu 13.10 64-bit

auch für Ubuntu 14.04 ohne Probleme. Wer aber nach dem Start Probleme hat das das Tastaturlayout nicht erkannt wird muss folgenden Eintrag ändern:

vim /opt/Citrix/ICAClient/config/wfclient.ini

anschließend den Parameter

KeyboardLayout = (User Profile)

ändern in z.B.

KeyboardLayout = GERMAN

Es wird zwar weiterhin ein Fehler angezeigt vor allem das die GTK nicht aufgerufen werden kann aber der Client kann zumindest mit einem vernünftigen Layout gestartet werden.

Magento mit aktueller PHP Version 5.4.+

Magento hat Probleme mit der aktuellen PHP Version um PDF’s für Rechnungen erzeugen zu können. Um diesen Fehler zu beheben muss im Zend Framework eine File angepasst werden.

Resultat: Funktioniert! 🙂

Auszug aus StackOverflow

This an incompatibility issue between PHP Version 5.4.4 and zend Framwork .

Fixed it by change in this function lib/Zend/Pdf/FileParserDataSource.php.

change

<code><span class="kwd" style="color: #00008b;">abstract</span><span class="kwd" style="color: #00008b;">public</span><span class="kwd" style="color: #00008b;">function</span><span class="pln" style="color: #000000;"> __construct</span><span class="pun" style="color: #000000;">();</span></code>

to

<code><span class="kwd" style="color: #00008b;">abstract</span><span class="kwd" style="color: #00008b;">public</span><span class="kwd" style="color: #00008b;">function</span><span class="pln" style="color: #000000;"> __construct</span><span class="pun" style="color: #000000;">(</span><span class="pln" style="color: #000000;">$filePath</span><span class="pun" style="color: #000000;">);</span></code>

Crossfit Games 2014

Bald ist es so weit. Crossfit Games 2014 starten in die nächste Runde. Nachdem 2013 schon überaus beeindruckend war gibt es noch ein paar Impressionen aus dem letzen Jahr.

In ein paar Tagen geht es die die nächste Runde. Games 2014, ich werde mir auf jeden Fall den Livestream reinziehen. Hier der Channel von Crossfit.

Weitere Informationen zu den Games, Athleten und co findet ihr auch unter games.crossfit.com

Crossfit – Schienbein offen

So ein Scheiß. Normalerweise beginnt man damit keine Sätze aber dieses mal trifft es voll zu. Enthusiasmus muss sein, Begeisterung bei Sport und körperlicher Ertüchtigung. Ich liebe es mich zu bewegen. Laufen, Springen, Gewichtheben oder seit knapp 8 Monaten Crossfit in „The Box“- Kulmbach.

Ralf Müller unser Crossfit Coach ist klasse, und die Mitstreiter die jeden Tag aufs neue Ihre Grenzen kennen lernen wollen. Einfach eine Klasse Mannschaft. Nächste Jahr greifen wir so richtig an. Egal ob CMAR, Crossfit Games oder andere Events die uns eine Herausforderung bietet.

Zurück zum eigentlichen Thema. Wie blöd darf/kann man sein. Boxjumps, so einfach wie es sich anhört sollte man meinen kann’s doch nicht anders sein. Hoch- Runter- von der Box, immer wieder und wieder. Aber irgendwann verlässt einem die Konzentration, innerhalb von Bruchteilen einer Sekunde rutscht man ab. Und dann?! … Offen… das Schienbein. Kurz fluchen, Schweiß aus dem Gesicht wischen und weiter gehts. Die letzen Reps werden durchgezogen. Danach ist Zeit nach dem Bein zu sehen.

Entkräftet und Fertig am Boden liegend begutachtet man sein Bein und stellt, mal wieder fest … offen. Selbe Stelle wie vor ein paar Wochen. Da gings aber gut aus. Nach 2- 3 Tagen war ein Grint gewachsen und man konnte sich wieder dem Crossfit und seinem eigenen Schweinehund widmen. Aber dieses mal war es anders. Mein offenes Bein, immer noch am siffen. Nach knapp 2 Wochen. Ich könnte verrückt werden. Letzte Woche Antibiotika, diese Woche Antibiotika. Gesund kann das auch nicht sein aber man versucht alles um schnell wieder fit zu werden. Entgegen dem eigenen Drang sich bewegen zu wollen sitzt man Stunden auf der Couch ab. Manche sind ganz froh darüber den Couchpotatoe zu mimen aber mich nervt’s nur.

Morgen geht’s wieder zur Ärztin. Mal sehen was dieses mal dabei raus kommt. Bisher hat weder der Chirurg noch die Hausärztin eine wirkliche Diagnose gestellt, die ich verstehen würde. 😉 Kopf hoch und keep on… Auf das die Tragödie bald rum ist. Ich freue mich wieder auf die Truppe.

Kleines Update, nichts für schwache nerven.
image