PDFPrintE-mail

JBoss Seam ohne Hibernate

Ohne JBoss Seam ist die JSF Entwicklung eine mühsame Angelegenheit. Diese rießige XML Datei namens faces.xml muss ständig erweitert und gepflegt werden. Schöner ist doch die Seam Variante mit den Annotations. Benutze ich aber JBoss Seam so bin ich auch gleich an die Architektur (JSF und Hibernate) welche Seam vorgibt gebunden. Oder doch nicht? Ich kann auch Seam ohne Hibernate, also ohne einen PersistenceContext in jeder Conversation zu öffnen benutzen. Und damit kann ich auch den damit verbundenen Problemen aus dem Weg gehen. Keine Frage, durch diesen PersistenceContext kann ich vieles einfacher gestallten. Nie wieder eine HibernateLazyInitializationException. Aber es entstehen eben auch Probleme durch die Architektur. Oder man möchte sie einfach nicht haben weil sie nicht zum diesem Produkt passt.

Damit wir Seam ohne PersistenceContext benutzen können ist jedoch ein wenig Arbeit mit verbunden. Folgende Schritte sind dafür nötig.

1. Transactionsteuerung in der components.xml deaktivieren:

...
<
core:init transaction-management-enabled="false"
/>
<
transaction:no-transaction
/>
...

2. Damit wir weiterhin den Vorteil eines EntityConverter benutzen können sind folgende Schritte zu erledigen:

Wir benötigen 2 neue Klassen, welche die vorhandenen Seam Klassen, "überschreiben". Das Überschreiben in Seam ist ein sehr einfache Angelegenheit. Wir müssen lediglich eine neue Klasse erzeugen und den Namen der bestehenden Seam Komponente wiederverwerden. In folgenden Listing: @Name("org.jboss.seam.ui.entityIdentifierStore"). Und darauf achten das der Install nicht vom Typ BUILD_IN ist.

EntityConverter.java

 
package com.osoboo.ui;

import static org.jboss.seam.ScopeType.CONVERSATION;

import java.io.Serializable;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;

import org.apache.commons.lang.StringUtils;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.faces.Converter;
import org.jboss.seam.annotations.intercept.BypassInterceptors;

/**
 * Used by s:entityConvert.
 */
@Name("org.jboss.seam.ui.EntityConverter")
@Scope(CONVERSATION)
@Install(precedence = Install.APPLICATION)
@Converter
@BypassInterceptors
public class EntityConverter implements javax.faces.convert.Converter, Serializable{
   
	private static final long serialVersionUID = -71231212574912331230L;

	/** */
	public Object getAsObject(FacesContext context, UIComponent component, String value) {
		if (value == null) {
			return null;
		}
		return EntityIdentifierStore.instance().get(value);
	}

	public String getAsString(FacesContext context, UIComponent component, Object value) {
		if (value == null) {
			return null;
		}
		
		String key = EntityIdentifierStore.instance().contains(value);
		if (! StringUtils.isBlank(key)) { 
			return key;
		}

		return EntityIdentifierStore.instance().put(value).toString();
	}
}

EntityIdentifierStore.java

 
package com.osoboo.ui;

import static org.jboss.seam.ScopeType.PAGE;

import java.rmi.server.UID;
import java.util.HashMap;
import java.util.Map;

import org.jboss.seam.Component;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.core.AbstractMutable;

import com.osoboo.dto.AbstractEntityDTO;


/**
 * Used by s:entityConvert.
 */
@Name("org.jboss.seam.ui.entityIdentifierStore")
@Install(precedence = Install.APPLICATION)
@Scope(PAGE)
public class EntityIdentifierStore extends AbstractMutable {
	
	private static final long serialVersionUID = -32726534254252681L;
	
	private Map storedElements = new HashMap();

	/**
	 * Put object into store.
	 */
	public String put(Object entity) {
		String key = resolveKey(entity);
		storedElements.put(key, entity);
		return key;
	}

	/**
	 * Get object from store.
	 */
	public Object get(String key) {
		return storedElements.get(key);
	}
	
	/**
	 * Look for this object in the store and returns his key. 
	 */
	public String contains(Object object) {
		for (Map.Entry entry : storedElements.entrySet()) {
			if (entry.getValue() == object) {
				entry.getKey();
			}
		}
		return null;
	}


	/**
	 * Resolve unique id for this element.
	 */
	private String resolveKey(Object element) {
		String key = null;
		if (element instanceof AbstractEntityDTO) {
			key = ((AbstractEntityDTO)element).getId();
		} else {
			key = new UID().toString();
		}
		return key;
	}

	
	public static EntityIdentifierStore instance() {
		if (!Contexts.isPageContextActive()) {
			throw new IllegalArgumentException("The page scope not active.");
		}
		return (EntityIdentifierStore) 
			Component.getInstance(EntityIdentifierStore.class);
	}
}

Ohne diese beiden Klassen kommt es zu folgendem Fehler:

 
type Exception report

message

description The server encountered an internal error () that prevented it from fulfilling this request.

exception

javax.servlet.ServletException: no transaction
	javax.faces.webapp.FacesServlet.service(FacesServlet.java:277)
	org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)
	org.jboss.seam.web.IdentityFilter.doFilter(IdentityFilter.java:40)
	org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
	org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:90)
	org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
	org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:73)
	org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:73)
	org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:177)
	org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:267)
	org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:380)
	org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:507)
	org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:56)
	org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
	org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:58)
	org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
	org.jboss.seam.web.HotDeployFilter.doFilter(HotDeployFilter.java:53)
	org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
	org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)
root cause

java.lang.UnsupportedOperationException: no transaction
	org.jboss.seam.transaction.NoTransaction.begin(NoTransaction.java:36)
	org.jboss.seam.util.Work.workInTransaction(Work.java:42)
	org.jboss.seam.transaction.TransactionInterceptor.aroundInvoke(TransactionInterceptor.java:89)
	org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
	org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:44)
	org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
	org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:107)
	org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:185)
	org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:103)
	org.jboss.seam.ui.JpaEntityLoader_$$_javassist_5.put(JpaEntityLoader_$$_javassist_5.java)
	org.jboss.seam.ui.EntityConverter.getAsString(EntityConverter.java:65)
	com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getFormattedValue(HtmlBasicRenderer.java:448)
	com.sun.faces.renderkit.html_basic.MenuRenderer.renderOption(MenuRenderer.java:480)
	com.sun.faces.renderkit.html_basic.MenuRenderer.renderOptions(MenuRenderer.java:759)
	com.sun.faces.renderkit.html_basic.MenuRenderer.renderSelect(MenuRenderer.java:819)
	com.sun.faces.renderkit.html_basic.MenuRenderer.encodeEnd(MenuRenderer.java:280)
	javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:861)
	org.jboss.seam.ui.util.cdk.RendererBase.renderChild(RendererBase.java:190)
	org.jboss.seam.ui.util.cdk.RendererBase.renderChildren(RendererBase.java:166)
	org.jboss.seam.ui.renderkit.ValidateAllRendererBase.doEncodeChildren(ValidateAllRendererBase.java:33)
	org.jboss.seam.ui.util.cdk.RendererBase.encodeChildren(RendererBase.java:92)
	javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
	org.jboss.seam.ui.util.cdk.RendererBase.renderChild(RendererBase.java:186)
	org.jboss.seam.ui.util.cdk.RendererBase.renderChildren(RendererBase.java:166)
	org.jboss.seam.ui.renderkit.DecorateRendererBase.doEncodeChildren(DecorateRendererBase.java:146)
	org.jboss.seam.ui.util.cdk.RendererBase.encodeChildren(RendererBase.java:92)
	javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
	javax.faces.component.UIComponent.encodeAll(UIComponent.java:936)
	javax.faces.render.Renderer.encodeChildren(Renderer.java:148)
	javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
	org.ajax4jsf.renderkit.RendererBase.renderChild(RendererBase.java:282)
	org.ajax4jsf.renderkit.RendererBase.renderChildren(RendererBase.java:262)
	org.ajax4jsf.renderkit.html.AjaxOutputPanelRenderer.encodeChildren(AjaxOutputPanelRenderer.java:78)
	javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
	org.ajax4jsf.renderkit.RendererBase.renderChild(RendererBase.java:282)
	org.ajax4jsf.renderkit.RendererBase.renderChildren(RendererBase.java:262)
	org.richfaces.renderkit.html.ModalPanelRenderer.doEncodeChildren(ModalPanelRenderer.java:385)
	org.richfaces.renderkit.html.ModalPanelRenderer.doEncodeChildren(ModalPanelRenderer.java:380)
	org.ajax4jsf.renderkit.RendererBase.encodeChildren(RendererBase.java:121)
	javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
	javax.faces.component.UIComponent.encodeAll(UIComponent.java:936)
	javax.faces.component.UIComponent.encodeAll(UIComponent.java:942)
	com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:592)
	org.ajax4jsf.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:108)
	org.ajax4jsf.application.AjaxViewHandler.renderView(AjaxViewHandler.java:196)
	com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:109)
	com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
	com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
	javax.faces.webapp.FacesServlet.service(FacesServlet.java:266)
	org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)
	org.jboss.seam.web.IdentityFilter.doFilter(IdentityFilter.java:40)
	org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
	org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:90)
	org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
	org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:73)
	org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:73)
	org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:177)
	org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:267)
	org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:380)
	org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:507)
	org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:56)
	org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
	org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:58)
	org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
	org.jboss.seam.web.HotDeployFilter.doFilter(HotDeployFilter.java:53)
	org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
	org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)