how can I get the value of " #{readeredit.reader.tel}" form the jsf form? [duplicate] - forms

I have started learning JSF, but sadly most tutorials out there present only a log in or a register section.
Can you point me to some more in depth examples? One thing I'm interested in is a page presenting a list of products. I'm on page home and I press on page products so that I can see the latest products added. And every time I visit the page, the product list will be created from the latest entries in the database. How can I handle this?
One way to solve this would be to create a session scoped managed bean in which I would place different entities updated through other managed beans. I found this kind of approach in some tutorials, but it seems quite difficult and clumsy.
Which would be the best approach to solve a thing like this? What is the correct usage of session scope in two-page master-detail user interface?

What is the correct usage of session scope
Use it for session scoped data only, nothing else. For example, the logged-in user, its settings, the chosen language, etcetera.
See also:
How to choose the right bean scope?
And every time I visit the page, the product list will be created from the latest entries in the database. How can I handle this?
Typically you use the request or view scope for it. Loading of the list should happen in a #PostConstruct method. If the page doesn't contain any <h:form>, then the request scope is fine. A view scoped bean would behave like a request scoped when there's no <h:form> anyway.
All "view product" and "edit product" links/buttons which just retrieve information (i.e. idempotent) whould be just plain GET <h:link> / <h:button> wherein you pass the entity identifier as a request parameter by <f:param>.
All "delete product" and "save product" links/buttons which will manipulate information (i.e. non-idempotent) should perform POST by <h:commandLink>/<h:commandButton> (you don't want them to be bookmarkable/searchbot-indexable!). This in turn requires a <h:form>. In order to preserve the data for validations and ajax requests (so that you don't need to reload/preinitialize the entity on every request), the bean should preferably be view scoped.
Note that you should basically have a separate bean for each view and also note that those beans doesn't necessarily need to reference each other.
So, given this "product" entity:
#Entity
public class Product {
#Id
private Long id;
private String name;
private String description;
// ...
}
And this "product service" EJB:
#Stateless
public class ProductService {
#PersistenceContext
private EntityManager em;
public Product find(Long id) {
return em.find(Product.class, id);
}
public List<Product> list() {
return em.createQuery("SELECT p FROM Product p", Product.class).getResultList();
}
public void create(Product product) {
em.persist(product);
}
public void update(Product product) {
em.merge(product);
}
public void delete(Product product) {
em.remove(em.contains(product) ? product : em.merge(product));
}
// ...
}
You can have this "view products" on /products.xhtml:
<h:dataTable value="#{viewProducts.products}" var="product">
<h:column>#{product.id}</h:column>
<h:column>#{product.name}</h:column>
<h:column>#{product.description}</h:column>
<h:column>
<h:link value="Edit" outcome="/products/edit">
<f:param name="id" value="#{product.id}" />
</h:link>
</h:column>
</h:dataTable>
#Named
#RequestScoped
public class ViewProducts {
private List<Product> products; // +getter
#EJB
private ProductService productService;
#PostConstruct
public void init() {
products = productService.list();
}
// ...
}
And you can have this "edit product" on /products/edit.xhtml:
<f:metadata>
<f:viewParam name="id" value="#{editProduct.product}"
converter="#{productConverter}" converterMessage="Unknown product, please use a link from within the system."
required="true" requiredMessage="Bad request, please use a link from within the system."
/>
</f:metadata>
<h:messages />
<h:form rendered="#{not empty editProduct.product}>
<h:inputText value="#{editProduct.product.name}" />
<h:inputTextarea value="#{editProduct.product.description}" />
...
<h:commandButton value="save" action="#{editProduct.save}" />
</h:form>
#Named
#ViewScoped
public class EditProduct {
private Product product; // +getter +setter
#EJB
private ProductService productService;
public String save() {
productService.update(product);
return "/products?faces-redirect=true";
}
// ...
}
And this converter for <f:viewParam> of "edit product":
#Named
#RequestScoped
public class ProductConverter implements Converter {
#EJB
private ProductService productService;
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (value == null || value.isEmpty()) {
return null;
}
try {
Long id = Long.valueOf(value);
return productService.find(id);
} catch (NumberFormatException e) {
throw new ConverterException("The value is not a valid Product ID: " + value, e);
}
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value == null) {
return "";
}
if (value instanceof Product) {
Long id = ((Product) value).getId();
return (id != null) ? String.valueOf(id) : null;
} else {
throw new ConverterException("The value is not a valid Product instance: " + value);
}
}
}
You can even use a generic converter, this is explained in Implement converters for entities with Java Generics.
See also:
How to navigate in JSF? How to make URL reflect current page (and not previous one)
JSF Controller, Service and DAO
JSF Service Layer
How to inject #EJB, #PersistenceContext, #Inject, #Autowired, etc in #FacesConverter?
Communication in JSF 2.0 - Contains several examples/hints

As a small improvement to what BalusC recommended, sometimes you can remove the required / requiredMessage part from the <f:viewParam> of your "details" screen and instead use the conditional rendering of the editing form (as BalusC did) with a reverse condition for recommending a specific link for the "list/master" screen or, even use a viewAction that would test the param and force a redirect to that list.

Related

How to add warning message on a wicket Form

I am adding a warning message using form.warn method but the warning message is not getting displayed. how do you add warning message on a wicket form
public class FormPanel extends BreadCrumbPanel {
public FormPanel(String id, IBreadCrumbModel breadCrumbModel)
{
super(id, breadCrumbModel);
Form<?> form = new Form<Void>("form");
form.add(new SaveButton("save"));
form.add(new FeedbackPanel("feedback"));
}
private class SaveButton extends Button {
private static final long serialVersionUID = 1L;
public SaveButton(String id) {
super(id);
}
#Override
public void onSubmit() {
validate(getForm());
}
}
validate(Form<?> form){
if(some logic)
form.warn(“message”);
}
}
You better move your validation logic to IValidator#validate() or IFormValidator#validate().
Currently you call it in Button#onSubmit(). That means Wicket believes everything is valid in your form fields and calls the last step - onSubmit(). Usually after onSubmit() you either render a completely different page or a new instance of the current page. In both cases the current page instance is lost together with its Form and its feedback messages.
If IValidator#validate() fails then Wicket will call onError() instead and re-render the current page instance.

Problems when using EntityFilteringFeature and SelectableEntityFilteringFeature with Jersey 2

I'm new to Jersey 2 and JAX-RS, so probably I'm missing something.
What I'm trying to do is a test program to define a coding style in rest services developing.
The test was written in JAVA and uses JERSEY 2.22.2, JDK 1.8.31, MOXY AS JSON Provider.
I defined a Resource with GET methods to support LIST/DETAIL. Due to the size of my POJO, I used some filters and everything was fine.
// 1) First of all I defined the annotation.
#Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
#Retention(RetentionPolicy.RUNTIME)
#Documented
#EntityFiltering
public #interface MyDetailView {
public static class Factory extends AnnotationLiteral<MyDetailView>
implements MyDetailView {
private Factory() {
}
public static MyDetailView get() {
return new Factory();
}
}
// 2) Once defined the annotation, I used to
// programmaticaly exclude the list of subItems in the response...
#XmlRootElement
public class MyPojo {
...
//*** THIS SHOULD BE FILTERED IF THE ANNOTATION IS NOT SPECIFIED IN THE RESPONSE ***
#MyDetailView
private List<SubItem> subItems = new ArrayList<SubItem>();
public List<SubItem> getSubItems() {
return subItems;
}
public void setSubItems(List<SubItem> subItems) {
this.subItems = subItems;
}
}
// 3) I registered the EntityFilteringFeature
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
....
register(EntityFilteringFeature.class);
}
// 4) Finally, I wrote the code to include/exclude the subItems
/*
The Resource class has getCollection() and getItem() methods...
getCollection() adds the annotation only if filterStyle="detail"
getItem() always add the annotation
*/
#Path(....)
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class MyResource extends SecuredResource {
//filterStyle -> "detail" means MyDetailAnnotation
#GET
public Response getCollection(
#QueryParam("filterStyle") String filterStyle,
#Context UriInfo uriInfo) {
//THIS CODE AFFECTS THE RESPONSE
boolean detailedResponse = "detail".equals(filterStyle);
Annotation[] responseAnnotations = detailedResponse
? new Annotation[0]
: new Annotation[]{MyDetailView.Factory.get()};
//pojo collection...
MyPagedCollection myCollection = new MyPagedCollection();
//.....
ResponseBuilder builder = Response.ok();
return builder.entity(myCollection, responseAnnotations).build();
}
#GET
#Path("/{id}")
public Response getItem(#PathParam("{id}") String idS, #Context UriInfo uriInfo) {
MyPOJO pojo = ...
Annotation[] responseAnnotations = new Annotation[]{MyDetailView.Factory.get()};
return Response.ok().entity(pojo, responseAnnotations).build();
}
}
After the first test, I tried to use the SelectableEntityFilteringFeature to allow the client to ask for specific fields in the detail, so I changed the ApplicationConfig
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
....
register(EntityFilteringFeature.class);
register(SelectableEntityFilteringFeature.class);
property(SelectableEntityFilteringFeature.QUERY_PARAM_NAME, "fields");
}
and I've add the "fields" QueryParam to the Resource getItem() method...
#GET
#Path("/{id}")
public Response getDetail(#PathParam({id}) String id,
#QueryParam("fields") String fields,
#Context UriInfo uriInfo) {
....
But as long as I registered the SelectableEntityFilteringFeature class, the EntityFilteringFeature class stopped working. I tried to add "fields" parameter to one of the Resource methods, it worked perfectly. But the MyDetailAnnotation was completely useless.
I tried to register it using a DynamicFeature
public class MyDynamicFeature implements DynamicFeature {
#Override
public void configure(ResourceInfo resourceInfo, FeatureContext context) {
if ("MyResource".equals(resourceInfo.getResourceClass().getSimpleName())
&& "getItem".equals(resourceInfo.getResourceMethod().getName())) {
//*** IS THE CORRECT WAY TO BIND A FEATURE TO A METHOD? ***
//
context.register(SelectableEntityFilteringFeature.class);
context.property(SelectableEntityFilteringFeature.QUERY_PARAM_NAME, "fields");
}
}
Now the questions:
1) Why registering both the SelectableEntityFilteringFeature feature breaks the EntityFilteringFeature?
2) What is the correct way to bind a feature to a method with the DynamicFeature interface?
Thanks in advance.
This is my first post to Stack Overflow, I hope it was written complaining the rules.
Short answer: you can't. It appears to be a bug as of 2.25.1 and up to 2.26(that I tested with). https://github.com/jersey/jersey/issues/3523
SelectableEntityFilteringFeature implictily registers EntityFilteringFeature (As mentioned here). So I don't see a need to add this.
Since you need Annotation based filtering, you can exclude registering SelectableEntityFilteringFeature.
You can just do,
// Set entity-filtering scope via configuration.
.property(EntityFilteringFeature.ENTITY_FILTERING_SCOPE, new Annotation[] {MyDetailView.Factory.get()})
// Register the EntityFilteringFeature.
.register(EntityFilteringFeature.class)
// Further configuration of ResourceConfig.
You can refer to this example for usage and this example for registering the filter.
So you can remove SelectableEntityFilteringFeature and try just the above mentioned way to register it.

Entities are unmanaged when using Extended PersistentContext

Environment:
JDK 1.8
WildFly 10.0.0.Final
I have following #Stateful bean
#Stateful
#SessionScoped
#Local(CdiStatefulEmployeeService.class)
public class CdiStatefulEmployeeBean implements CdiStatefulEmployeeService {
#PersistenceContext(name = "employees", type = PersistenceContextType.EXTENDED)
EntityManager extendedEm;
private Employee cached;
#Override
public String service() {
cached = extendedEm.find(Employee.class, 499983);
return cached.getFirstName();
}
#Override
public String updateEntity() {
cached.setFirstName("Uri2");
//extendedEm.flush(); -- Line 1
return cached.getFirstName();
}
}
and following Servlet client
#WebServlet("/atInjectedStatefulEjbClient")
public class AtInjectedStatefulEjbClient extends HttpServlet {
#Inject
CdiStatefulEmployeeService statefulBean;
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession(true);
resp.setContentType("text/plain");
PrintWriter pw = resp.getWriter();
pw.println(statefulBean.service());
pw.println();
pw.println(statefulBean.updateEntity());
session.invalidate();
pw.flush();
pw.close();
}
}
Observation: Calling bean.updateEntity() method is not automatically saving the changes i.e. setting first name to "Uri2".
Question : Arent the entities managed across the calls in case of extended persistence context ?
Calling the flush() (i.e. uncommenting Line 1) has no effect either. Basically the entity is not managed in the updateEntity() call. I find this strange. Any thoughts ?
UPDATE:
Just to rule out the possibility, tried with same code but with following
No #SessionScoped
No #Inject (replaced with JDNI lookup inside servlet doGet())
Added #Remove method in the bean
Have servlet doGet() invoke #Remove once it is done with calling other 2 methods
Result : Same issue. Entity is not managed after first service call
Rakesh
Assuming that service method is called before updateEntity shows described behavior: Transaction attribute of service method is default, which means that, as you pointed out in your comment on updateEntity, the transaction is committed at end of service call. This commit makes the cached entity unmanaged. I suggest to annotate service method with #TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) which should keep cached entity managed and subsequent call of updateEntity finds managed entity.
Usually, with extended persistence contexts the facade EJB classes are annotated with #TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) and only EJB's methods that should commit get a different transaction attribute (see for example article Domain-driven design with Java EE 6).
Never ever inject STATEFUL (session dependent) beans into servlets (used by many users = by many sessions). If you use CMT the commit of the transaction will be executed after the call of the #Remove marked method. Where is it? It can be empty but it is critical at stateful beans.
But It would be a viable solution:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form>
<h:inputText value="#{employeeMB.emplyeeName}"/>
<h:commandButton value="Submit" action="#{employeeMB.onSubmit}"/>
</h:form>
</h:body>
</html>
#ManagedBean
#SessionScoped
#Getter
#Setter
public class EmployeeMB
{
private String employeeName;
#EJB
private EmployeeSB employeeSB;
public void onSubmit()
{
employeeSB.persist( employeeName );
employeeName = "";
}
}
#Stateless
#LocalBean
public class EmployeeSB
{
#PersistenceContext
private EntityManager em;
public void persist( String employeeName_ )
{
Employee e = new Employee();
e.setName( employeeName_ );
em.persist( e );
}
}
Seems to be a bug in WildFly. All the documentation (Spec, books etc..) point out that Extended context meant to prevent entities from becoming detached when the transaction ends.
Filed Wildfly Issue : https://issues.jboss.org/browse/WFLY-6383

Cache JPA Entities with EJB

[The real question is marked in bold down. Here follows an as short as possible explanation of my situation]
I have the following JPA Entities:
#Entity Genre{
private String name;
#OneToMany(mappedBy = "genre", cascade={CascadeType.MERGE, CascadeType.PERSIST})
private Collection<Novel> novels;
}
#Entity
class Novel{
#ManyToOne(cascade={CascadeType.MERGE, CascadeType.PERSIST})
private Genre genre;
private String titleUnique;
#OneToMany(mappedBy="novel", cascade={CascadeType.MERGE, CascadeType.PERSIST})
private Collection<NovelEdition> editions;
}
#Entity
class NovelEdition{
private String publisherNameUnique;
private String year;
#ManyToOne(optional=false, cascade={CascadeType.PERSIST, CascadeType.MERGE})
private Novel novel;
#ManyToOne(optional=false, cascade={CascadeType.MERGE, CascadeType.PERSIST})
private Catalog appearsInCatalog;
}
#Entity
class Catalog{
private String name;
#OneToMany(mappedBy = "appearsInCatalog", cascade = {CascadeType.MERGE, CascadeType.PERSIST})
private Collection<NovelEdition> novelsInCatalog;
}
The idea is to have several Novels, belonging each to a specific Genre, for which can exist more than an edition (different publisher, year, etc). For semplicity a NovelEdition can belong to just
one Catalog, being such a Catalog represented by such a text file:
Catalog: Name Of Catalog 1
-----------------------
"Title of Novel 1", "Genre1 name","Publisher1 Name", 2009
"Title of Novel 2", "Genre1 name","Pulisher2 Name", 2010
.....
Catalog: Name Of Catalog 2
-----------------------
"Title of Novel 1", "Genre1 name","Publisher2 Name", 2011
"Title of Novel 2", "Genre1 name","Pulisher1 Name", 2011
.....
Each entity has associated a Stateless EJB that acts as a DAO, using a Transaction Scoped EntityManager. For example:
#Stateless
public class NovelDAO extends AbstractDAO<Novel> {
#PersistenceContext(unitName = "XXX")
private EntityManager em;
protected EntityManager getEntityManager() {
return em;
}
public NovelDAO() {
super(Novel.class);
}
//NovelDAO Specific methods
}
I am interested at when the catalog files are parsed and the corresponding entities are built (I usually read a whole batch of Catalogs at a time).
Being the parsing a String-driven procedure, I don't want to repeat actions like novelDAO.getByName("Title of Novel 1") so I would like to use a centralized cache for mappings of type String-Identifier->Entity object.
Currently I use 3 Objects:
1) The file parser, which does something like:
final CatalogBuilder catalogBuilder = //JNDI Lookup
//for each file:
String catalogName = parseCatalogName(file);
catalogBuilder.setCatalogName(catalogName);
//For each novel edition
String title= parseNovelTitle();
String genre= parseGenre();
...
catalogBuilder.addNovelEdition(title, genre, publisher, year);
//End foreach
catalogBuilder.build();
2) The CatalogBuilder is a Stateful EJB which uses the Cache and gets re-initialized each time a new Catalog file is parsed and gets "removed" after a catalog is persisted.
#Stateful
public class CatalogBuilder {
#PersistenceContext(unitName = "XXX", type = PersistenceContextType.EXTENDED)
private EntityManager em;
#EJB
private Cache cache;
private Catalog catalog;
#PostConstruct
public void initialize() {
catalog = new Catalog();
catalog.setNovelsInCatalog(new ArrayList<NovelEdition>());
}
public void addNovelEdition(String title, String genreStr, String publisher, String year){
Genre genre = cache.findGenreCreateIfAbsent(genreStr);//**
Novel novel = cache.findNovelCreateIfAbsent(title, genre);//**
NovelEdition novEd = new NovelEdition();
novEd.setNovel(novel);
//novEd.set publisher year catalog
catalog.getNovelsInCatalog().add();
}
public void setCatalogName(String name) {
catalog.setName(name);
}
#Remove
public void build(){
em.merge(catalog);
}
}
3) Finally, the problematic bean: Cache. For CatalogBuilder I used an EXTENDED persistence context (which I need as the Parser executes several succesive transactions) together with a Stateful EJB;
but in this case I am not really sure what I need. In fact, the cache:
Should stay in memory until the parser is finished with its job,
but not longer (should not be a singleton) as the parsing is just a
very particular activity which happens rarely.
Should keep all of
the entities in context, and should return managed entities form
methods marked with *, otherwise the attempt to persist the catalog
should fail (duplicated INSERTs)..*
Should use the same
persistence context as the CatalogBuilder.
What I have now is :
#Stateful
public class Cache {
#PersistenceContext(unitName = "XXX", type = PersistenceContextType.EXTENDED)
private EntityManager em;
#EJB
private sessionbean.GenreDAO genreDAO;
//DAOs for other cached entities
Map<String, Genre> genreName2Object=new TreeMap<String, Genre>();
#PostConstruct
public void initialize(){
for (Genre g: genreDAO.findAll()) {
genreName2Object.put(g.getName(), em.merge(g));
}
}
public Genre findGenreCreateIfAbsent(String genreName){
if (genreName2Object.containsKey(genreName){
return genreName2Object.get(genreName);
}
Genre g = new Genre();
g.setName();
g.setNovels(new ArrayList<Novel>());
genreDAO.persist(t);
genreName2Object.put(t.getIdentifier(), em.merge(t));
return t;
}
}
But honestly I couldn't find a solution which satisfies these 3 points at the same time. For example, using another stateful bean with an extended persistence context would work for the 1st parsed file, but I have
no idea what should happen from the 2nd file on.. Indeed for the first file the PC will be created and propagated from CatalogBuilder to Cache, which will then use the same PC. But after build() returns,
the PC of CatalogBuilder should (I guess) be removed and re-created during the successive parsing, although the PC of Cache should stay "alive": shouldn't in this case an exception being thrown? Another problem is
what to do when the Cache bean is passivated. Currently I get the exception:
"passivateEJB(), Exception caught ->
java.io.IOException: java.io.IOException
at com.sun.ejb.base.io.IOUtils.serializeObject(IOUtils.java:101)
at com.sun.ejb.containers.util.cache.LruSessionCache.saveStateToStore(LruSessionCache.java:501)"
Hence, I have no idea how to implement my cache. How would you solve the problem?
EclipseLink configuration :
You can have specify property in configuration file for all entites.
<property name="eclipselink.cache.shared.default" value="true"/>
At entity level with #Cache annotation, specifying different attributes.
General JPA configuration :
At entity level by using #Cacheable annotation with value attribute as true.
Specifying the retrieval mode by CacheRetrieveMode, attribute USE to enable else BYPASS.
entityManager.setProperty("javax.persistence.cache.retrieveMode", CacheRetrieveMode.USE);
Configuring the storage in cache by CacheStoreMode with attribute BYPASS, USE or REFRESH.
entityManager.setProperty("javax.persistence.cache.storeMode",CacheStoreMode.REFRESH);
Cache interface represents shared cache. To remove all or some cached entity, you can call one of the evict methods. You can get reference of cache interface from EntityManagerFactory.

How to make a form submit when its rendered based on a value in a request scoped bean

I discovered a problem in my little program, and Im wondering if anyone have any tips or advice on how to solve this problem as best as possible.
I have the bean testBean which is in request scope. It contains the following:
public class testBean {
private boolean internal = false;
private String input = "";
public String internalTrue() {
System.out.println("Set internal true");
setInternal(true);
return null;
}
public String submitForm() {
System.out.println("");
return null;
}
public boolean isInternal() {
return internal;
}
public void setInternal(boolean internal) {
this.internal = internal;
}
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
}
My file welcomeJSF.jsp contains this:
<f:view>
<h:form>
<h:commandButton value="Set internal true" action="#{testBean.internalTrue}" />
</h:form>
<h:panelGrid columns="1" rendered="#{testBean.internal}">
<h:form>
<h:outputText value="JavaServer Faces" /><h:inputText value="#{testBean.input}" />
<h:commandButton value="Go" action="#{testBean.submitForm}" />
</h:form>
</h:panelGrid>
</f:view>
When I run the application Im presented with the button "Set internal true". I click it and Im presented with the form where I have the button "Go". Clicking "Go" does not trigger the method in my bean, most likely because of the field actually not being rendered on the server anymore, and thus it wont run the method. Is there any smart solutions to this?
In advance, thanks for your time.
The children of the panel will never decode input because its rendered attribute always evaluates to false during the APPLY REQUEST VALUES phase. This is a sensible thing to do from a security point of view.
(source: ibm.com)
One thing you could do is take advantage of the fact that JSF components maintain state for the lifetime of the view.
The new bean:
public class TestBean {
private String input = null;
private UIComponent panel;
public String internalTrue() {
panel.setRendered(true);
return null;
}
public String submitForm() {
panel.setRendered(false);
System.out.println("submitForm");
return null;
}
public UIComponent getPanel() { return panel; }
public void setPanel(UIComponent panel) { this.panel = panel; }
public String getInput() { return input; }
public void setInput(String input) { this.input = input; }
}
The new view bound to the bean:
<f:view>
<h:form>
<h:commandButton value="Set internal true"
action="#{testBean.internalTrue}" />
</h:form>
<h:panelGrid binding="#{testBean.panel}" columns="1"
rendered="false">
<h:form>
<h:outputText value="JavaServer Faces" />
<h:inputText value="#{testBean.input}" />
<h:commandButton value="Go" action="#{testBean.submitForm}" />
</h:form>
</h:panelGrid>
</f:view>
Using the binding attribute on the panelGrid will cause setPanel to be called when the view is created/restored.
Note that you may have some testing to do depending on how your implementation's and/or libraries' StateManager stores views between requests (which may in turn be affected by the javax.faces.STATE_SAVING_METHOD init parameter). The view might be stored in a hidden field in the form, in the session keyed to the view ID (which may cause collisions with multiple browser windows), in the session keyed to a unique ID created by a GET or JSF navigation, or by some completely custom mechanism. The pluggable nature of the framework makes it versatile, but in this case it means you need to double-check how your implementation behaves.