Chciałbym programowo utworzyć instancję komponentów złożonych lub znaczników.Jak programowo utworzyć komponent złożony lub komponent znacznika?
Ta instancja byłaby wykonywana przez niestandardowy komponent, zwykle dodając te komponenty kompozytowe lub znaczniki jako elementy podrzędne.
Najlepszą odpowiedzią znalezioną podczas przeszukiwania forów jest: http://www.java.net/node/701640#comment-791881. Wygląda bardzo podobnie do innej odpowiedzi znalezionej na tym forum: How to programmatically or dynamically create a composite component in JSF 2.
Podczas pracy nad tym pytaniem, w końcu napisałem kod, który działa na złożony instanciation za pomocą MyFaces (przykłady w linku wydają się być specyficzne dla Mojarra). I skopiować go tam zajęło mi trochę czasu, aby ją napisać i mam nadzieję, że to pomoże ktoś inny:
public UIComponent instantiateComposite(String namespace, String componentName) {
FacesContext ctx = FacesContext.getCurrentInstance();
Resource resource = ctx.getApplication().getResourceHandler().createResource(componentName + ".xhtml", namespace);
UIComponent cc = ctx.getApplication().createComponent(ctx, resource);
UIPanel panel = (UIPanel) ctx.getApplication().createComponent(UIPanel.COMPONENT_TYPE);
// set the facelet's parent
cc.getFacets().put(UIComponent.COMPOSITE_FACET_NAME, panel);
FaceletFactory ff = (DefaultFaceletFactory) DefaultFaceletFactory.getInstance();
if(ff == null) {
FaceletViewDeclarationLanguage vdl = new FaceletViewDeclarationLanguage(ctx);
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, ctx);
ff = (FaceletFactory) createFaceletFactory.invoke(vdl, ctx, compiler);
} catch (IllegalAccessException ex) {
Logger.getLogger(SenatDataTableEntryDetail.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalArgumentException ex) {
Logger.getLogger(SenatDataTableEntryDetail.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(SenatDataTableEntryDetail.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchMethodException ex) {
Logger.getLogger(SenatDataTableEntryDetail.class.getName()).log(Level.SEVERE, null, ex);
} catch (SecurityException ex) {
Logger.getLogger(SenatDataTableEntryDetail.class.getName()).log(Level.SEVERE, null, ex);
}
}
try {
Facelet facelet = ff.getFacelet(resource.getURL());
facelet.apply(ctx, panel);
} catch (IOException e) {
e.printStackTrace();
}
return cc;
}
Proszę nie zwracać uwagę na brzydkie obsługi wyjątków: to jest tak samo automatycznie generowane przez NetBeans ... ja zapyta twórców MyFaces, czy istnieje sposób na uniknięcie brzydkich hacków refleksyjnych.
Jak mogę zrobić to samo z elementów znaczników, to znaczy elementy zadeklarowane jak:
<tag>
<description>blah blah</description>
<tag-name>myWonderfulTag</tag-name>
<source>tags/mwl/myWonderfulTag.xhtml</source>
<!-- attributes -->
</tag>
w TagLib.
Z góry dziękuję.