使用JSF 2 / MyFaces的Seam Mail

时间:2013-12-05 17:52:10

标签: jsf-2 myfaces seam2

是否有人使用JSF的MyFaces 2.1.x实现使用JSF 2运行Seam Mail(Seam 2.3)?

我无法使Seam Mail工作,因为无法创建Seam的org.jboss.seam.faces.renderer组件。它具有与com.sun.faces.facelets.Facelet的类依赖关系,并且MyFaces中不存在此类。

@Scope(ScopeType.STATELESS)
@BypassInterceptors
@Name("org.jboss.seam.faces.renderer")
@AutoCreate
@Install(value = true, precedence = Install.BUILT_IN,
  classDependencies = "com.sun.faces.facelets.Facelet")
public class FaceletsRenderer extends Renderer {
    ...
}

因此,以下语句失败,并且“@In属性需要非空值”异常。

@In(create = true)
private Renderer renderer;

我该怎么办?我是否还应该从Mojarra实现添加jsf-api?!

干杯 弗兰克

1 个答案:

答案 0 :(得分:3)

好的我修好了!

我刚用自己的组件替换了错误的Seam FaceletsRenderer:

@Scope(ScopeType.STATELESS)
@BypassInterceptors
@Name("org.jboss.seam.faces.renderer")
@AutoCreate
@Install(value = true, precedence = Install.APPLICATION)
// dependency to the evil Sun JSF class is removed:
// , classDependencies = "com.sun.faces.facelets.Facelet")
public class FaceletsRenderer extends Renderer {

    /**
     * Render the viewId, anything written to the JSF ResponseWriter is returned
     */
    @Override
    public String render(final String viewId) {
        // call our fixed RendererRequest class instead of the original one.
        de.jw.filesio.webapp.renderer.RendererRequest rendererRequest = new de.jw.filesio.webapp.renderer.RendererRequest(
                viewId);
        try {
            rendererRequest.run();
        } catch (IOException e) {
            throw new RuntimeException("error rendering " + viewId, e);
        }
        return rendererRequest.getOutput();
    }

}

Seam-Ui的原始RendererRequest类与Sun JSF结合良好,因此您还必须更换它。只需要修复方法faceletForViewId(String)。你走了:

    /**
     * Get a Facelet for a URL
     */
    protected Facelet faceletForViewId(String viewId) throws IOException {
        URL url = ResourceLoader.instance().getResource(viewId);
        if (url == null) {
            throw new IllegalArgumentException("resource doesn't exist: " + viewId);
        }

        // OLD CODE tightly coupled to Sun JSF
        // return
        // ApplicationAssociate.getCurrentInstance().getFaceletFactory().getFacelet(url);

        // NEW CODE for MyFaces
        // see
        // http://stackoverflow.com/questions/15813582/how-to-programmatically-instantiate-a-composite-component-or-a-tag-component
        FaceletFactory ff = DefaultFaceletFactory.getInstance();
        if (ff == null) {
            FaceletViewDeclarationLanguage vdl = new FaceletViewDeclarationLanguage(facesContext);

            Method createCompiler = null;
            Method createFaceletFactory = null;
            try {
                createCompiler = FaceletViewDeclarationLanguage.class.getDeclaredMethod("createCompiler",
                        FacesContext.class);
                createFaceletFactory = FaceletViewDeclarationLanguage.class.getDeclaredMethod("createFaceletFactory",
                        FacesContext.class, org.apache.myfaces.view.facelets.compiler.Compiler.class);
                createCompiler.setAccessible(true);
                createFaceletFactory.setAccessible(true);
                org.apache.myfaces.view.facelets.compiler.Compiler compiler = (org.apache.myfaces.view.facelets.compiler.Compiler) createCompiler
                        .invoke(vdl, facesContext);
                ff = (FaceletFactory) createFaceletFactory.invoke(vdl, facesContext, compiler);
            } catch (Exception ex) {
                log.error("Error creating FaceletFactory.", ex);
            }

        }

        Facelet facelet = null;
        try {

            facelet = ff.getFacelet(url);

        } catch (Exception ex) {
            log.error("Error creating facelet for url " + url, ex);
        }

        log.debug("Successfully created facelet for " + url + ": " + facelet);

        return facelet;
    }

我希望这有助于其他人面对我的问题。