2
votes

I'm in the process of writing a set of custom PrimeFaces components, using PrimeFaces 5.0 and running inside JBoss EAP 6.2.

I'm first building a custom component that renders a bog-standard html <input/>; tag as an initial proof of concept.

The short version of my problem:

With my namespace defined as st, the tag <st:input/> renders not an <input/> tag... but <st:input/> </st:input>.

The long version:

  1. I have two projects set up for this. The set of PrimeFaces custom components lives inside a maven project built with NetBeans. The jar need to be redistributable, and I deploy this onto my app server.

The second project is a showcase for the custom components.

  1. The custom component project is set up in the following way:

2.1 in the faces-config.xml:

<faces-config
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd"
    version="2.1">
    <name>myfacestest</name> 
</faces-config>

2.2 In myfacestest.taglib.xml I define my input tag:

<?xml version="1.0"?>
<facelet-taglib version="2.0"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
    id="st">
    <namespace>http://org.myfacestest.faces/ui</namespace>
    <tag>
        <tag-name>input</tag-name>
        <component>
            <component-type>org.myfacestest.faces.Input</component-type>
            <renderer-type>org.myfacestest.faces.InputRenderer</renderer-type>
        </component>
    </tag>
</facelet-taglib>

2.3 In Input.java (my custom component) I do the following:

@FacesComponent(value = Input.COMPONENT_TYPE)
@ResourceDependencies(
    {@ResourceDependency(library = "primefaces", name = "jquery/jquery.js"), 
    @ResourceDependency(library = "primefaces", name = "primefaces.js"), 
    @ResourceDependency(library = "myfacestest", name = "input.js"), 
    @ResourceDependency(library = "myfacestest/css", name = "input.css")})

    public class Input extends UIInput implements Widget {
        public static final String COMPONENT_TYPE = "org.myfacestest.faces.Input";
        public static final String COMPONENT_FAMILY = "org.myfacestest.faces.components";

      public String getFamily() {
          return COMPONENT_FAMILY;
      }
    ...

2.4 The renderer for this component contains the following:

@FacesRenderer(componentFamily = Input.COMPONENT_FAMILY, rendererType = InputRenderer.RENDERER_TYPE)
public class InputRenderer extends CoreRenderer {

    public static final String RENDERER_TYPE = "org.myfacestest.faces.components.InputRenderer";

    @Override
    public void decode(FacesContext context, UIComponent component) {
        String submittedValue = (String) context.getExternalContext().getRequestParameterMap().get(component.getClientId(context));
        ((Input) component).setSubmittedValue(submittedValue);
    }

    @Override
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
        this.encodeMarkup(context, (Input) component);
        this.encodeScript(context, (Input) component);
    }

    private void encodeMarkup(FacesContext context, Input input) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        //Object value = input.getValue() != null ? input.getValue() : 0;

        writer.startElement("input", input);
        writer.writeAttribute("id", input.getClientId(), null);
        writer.writeAttribute("name", input.getClientId(), null);
        writer.endElement("input");
    }

    private void encodeScript(FacesContext context, Input component) throws IOException {
        String clientId = component.getClientId();
        String widgetVar = component.resolveWidgetVar();

        WidgetBuilder wb = getWidgetBuilder(context);
        wb.initWithDomReady("Input", widgetVar, clientId);
        wb.finish();
    }
...

2.5 Since this jar is deployed as a module on my application server, I have my-faces-test-0.1.jar (named via the Maven POM) deployed in the following folder inside jboss:

modules/system/layers/base/org/myfacestest/faces/main

with the following inside my module.xml:

<module xmlns="urn:jboss:module:1.1" name="org.myfacestest.faces">
<resources>
    <resource-root path="my-faces-test-0.1.jar"/>
</resources>
<dependencies>
</dependencies>
</module>
  1. My showcase project is set up in the following way.

3.1 Since I deploy this to my jboss app server, I've added the following in my jboss-deployment-structure.xml:

<module name="org.myfacestest.faces"/>

3.2 I have an xhtml that uses the tag as follows:

<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui"
    xmlns:t="http://myfaces.apache.org/tomahawk"
    xmlns:st="http://org.myfacestest.faces/ui"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    >

3.3 In the same file, inside the <h:body> and <h:form> elements:

<st:input/>

Given this setup, why would the custom component not render? There is nothing in my jboss logs, even with logging levels set to debug.

1
Try adding export true to expose the xml hidden in the my-faces-test-0.1.jar <module name="org.myfacestest.faces" export="true" meta-inf="export"/> - Kenneth Clark
Thank you... this fixed it! This also explains why I couldn't even hit breakpoints inside my renderer. - johndou

1 Answers

0
votes

You can expose the XML configs in your JAR my-faces-test-0.1.jar by adding the export true tag to the jboss-deployment-structure.xml

<module name="org.myfacestest.faces" export="true" meta-inf="export"/> this will expose the dependency to the EAR / WAR