2013-11-28 2 views
1

Я работаю над приложением, в которое я хотел бы включить динамический контент XHTML из потока. Чтобы справиться с этим я написал расширение taghandler, который сбрасывает динамическое содержимое XHTML для вывода компонента, какВключить динамический контент, содержащий теги/компоненты JSF из потока

UIOutput htmlChild = (UIOutput) ctx.getFacesContext().getApplication().createComponent(UIOutput.COMPONENT_TYPE); 
htmlChild.setValue(new String(outputStream.toByteArray(), "utf-8")); 

Это прекрасно работает для содержания XHTML, который не имеет JSF тегов. Если у меня есть теги JSF в моем динамическом XHTML-контенте, например <h:inputText value="#{bean.item}"/>, тогда они печатаются как обычный текст. Я хочу, чтобы они отображались как поля ввода. Как я могу это достичь?

+0

Это ByteArrayOutputStream, которая была заполнена с помощью инструмента из моего приложения. Этот ByteArrayOutputStream содержит сгенерированное содержимое xhtml. – user3027786

+0

Помогает ли писать пользовательский taglib JSP? как я понял, они находятся на вершине жизненного цикла JSF. – user3027786

+0

@BalusC работает с механизмом Resourcehandler, основанным на временном файле, для ? Обычно обработчик ресурсов предназначен для статических ресурсов. Я не вижу больше вашего предлагаемого фрагмента кода здесь. – user3027786

ответ

1

По существу, вы должны использовать <ui:include> в сочетании с обычным ResourceHandler, который может вернуть ресурс в аромате URL. Поэтому, имея OutputStream, вы действительно должны записывать его в файл (temp), чтобы получить из него URL.

E.g.

<ui:include src="/dynamic.xhtml" /> 

с

public class DynamicResourceHandler extends ResourceHandlerWrapper { 

    private ResourceHandler wrapped; 

    public DynamicResourceHandler(ResourceHandler wrapped) { 
     this.wrapped = wrapped; 
    } 

    @Override 
    public ViewResource createViewResource(FacesContext context, String resourceName) { 
     if (resourceName.equals("/dynamic.xhtml")) { 
      try { 
       File file = File.createTempFile("dynamic-", ".xhtml"); 

       try (Writer writer = new FileWriter(file)) { 
        writer 
         .append("<ui:composition") 
         .append(" xmlns:ui='http://java.sun.com/jsf/facelets'") 
         .append(" xmlns:h='http://java.sun.com/jsf/html'") 
         .append(">") 
         .append("<p>Hello from a dynamic include!</p>") 
         .append("<p>The below should render as a real input field:</p>") 
         .append("<p><h:inputText /></p>") 
         .append("</ui:composition>"); 
       } 

       final URL url = file.toURI().toURL(); 
       return new ViewResource(){ 
        @Override 
        public URL getURL() { 
         return url; 
        } 
       }; 
      } 
      catch (IOException e) { 
       throw new FacesException(e); 
      } 
     } 

     return super.createViewResource(context, resourceName); 
    } 

    @Override 
    public ResourceHandler getWrapped() { 
     return wrapped; 
    } 

} 

(предупреждение: основной пример стартового это создает новый временный файл при каждом запросе, система повторного использования/кэш должен быть изобретены самостоятельно)

который зарегистрирован в faces-config.xml следующим образом:

<application> 
    <resource-handler>com.example.DynamicResourceHandler</resource-handler> 
</application> 

Примечание: все вышеперечисленное предназначено для JSF 2.2. Для пользователей JSF 2.0/2.1, наткнувшихся на этот ответ, вместо этого вы должны использовать ResourceResolver, для чего в этом ответе можно найти пример: Obtaining Facelets templates/files from an external filesystem or database. Важное примечание: ResourceResolver - deprecated в JSF 2.2 в пользу ResourceHandler#createViewResource().

+0

Я искал способ, которым нам не нужно хранить временный файл на веб-сервере. Нет ли альтернативного способа, который работает непосредственно в данных памяти? Возможно, с пользовательским jsf компонентом/тегом и т. Д. – user3027786

+0

Вы можете создать только пользовательский 'URLStreamHandlerFactory' и' URLStreamHandler'. Невозможно привести примеры из головы, поэтому на этот вопрос нет ответа. – BalusC

+0

Вопрос: Возможно ли получить доступ к объекту бэкбона и/или передать определенные параметры обработчику ресурсов? – user3027786

0

Мое решение для JSF 2.2 и обычая URLStream Handler

общественного класса DatabaseResourceHandlerWrapper расширяет ResourceHandlerWrapper {

private ResourceHandler wrapped; 

@Inject 
UserSessionBean userBeean; 

public DatabaseResourceHandlerWrapper(ResourceHandler wrapped) { 
    this.wrapped = wrapped; 
} 

@Override 
public Resource createResource(String resourceName, String libraryName) { 
    return super.createResource(resourceName, libraryName); //To change body of generated methods, choose Tools | Templates. 
} 

@Override 
public ViewResource createViewResource(FacesContext context, String resourceName) { 
    if (resourceName.startsWith("/dynamic.xhtml?")) { 
     try { 
      String query = resourceName.substring("/dynamic.xhtml?".length()); 
      Map<String, String> params = splitQuery(query); 
      //do some query to get content 
      String content = "<ui:composition" 
        + " xmlns='http://www.w3.org/1999/xhtml' xmlns:ui='http://java.sun.com/jsf/facelets'" 
        + " xmlns:h='http://java.sun.com/jsf/html'> MY CONTENT" 
        + "</ui:composition>"; 

      final URL url = new URL(null, "string://helloworld", new MyCustomHandler(content)); 
      return new ViewResource() { 
       @Override 
       public URL getURL() { 
        return url; 
       } 
      }; 
     } catch (IOException e) { 
      throw new FacesException(e); 
     } 
    } 

    return super.createViewResource(context, resourceName); 
} 

public static Map<String, String> splitQuery(String query) throws UnsupportedEncodingException { 
    Map<String, String> params = new LinkedHashMap<>(); 
    String[] pairs = query.split("&"); 
    for (String pair : pairs) { 
     int idx = pair.indexOf("="); 
     params.put(URLDecoder.decode(pair.substring(0, idx), "UTF-8"), URLDecoder.decode(pair.substring(idx + 1), "UTF-8")); 
    } 
    return params; 
} 

@Override 
public ResourceHandler getWrapped() { 
    return wrapped; 
} 

static class MyCustomHandler extends URLStreamHandler { 

    private String content; 

    public MyCustomHandler(String content) { 
     this.content = content; 
    } 

    @Override 
    protected URLConnection openConnection(URL u) throws IOException { 
     return new UserURLConnection(u, content); 
    } 

    private static class UserURLConnection extends URLConnection { 

     private String content; 

     public UserURLConnection(URL url, String content) { 
      super(url); 
      this.content = content; 
     } 

     @Override 
     public void connect() throws IOException { 
     } 

     @Override 
     public InputStream getInputStream() throws IOException { 
      return new ByteArrayInputStream(content.getBytes("UTF-8")); 
     } 
    } 

} 

}

Смежные вопросы