I am an applications programmer doing my first JSF 2.0 web site and confess that I don't know as much as I should about JSF. I have been pooring over documents for months and, thanks to these forums in particular, have not gotten stuck up to this point. The bulk of the web site is finished and working and the backing bean used here is used elsewhere without problems.
I have a serialised search criteria object that needs to be submitted from an applet to a backing bean, via a servlet. A backing bean method then processes the search criteria data and applies it to a list of products, held in a database, and then displays the list of ranked products in a new JSF page.
All attempts to open a results page with the correct data have failed. The navigation-case "return "process_MainSearchResult";" is not doing anything in the backing bean (see backing bean code down further and faces-config entry). I have tried opening a results page from the applet using appletContext.showDocument (see below) but the new page does not have the backing bean that the search criteria object was passed to and therefore none of the correct data.
Note that setting POST on the setRequestMethod in the applet has no effect; it always uses a service. If setDoInput and setDoOutput are not set to true and a response sent from the servlet back to the applet then the submitted object is not sent and nothing happens. I suspect that this is at the core of my problems but altering it in any way stops the serialised object from being submitted successfully.
As it stands, the object is successfully sent to the backing bean but the new page will not load with the correct data (using the showDocument in the applet rather than the redirect in the servlet). Is there a way of setting the original backing bean on the new web page or am I doing this all wrong?
Web server is Glassfish 3.x, IDE is Netbeans 7.0.1, System is WinXP. Backing bean class is 'ProductSelection'; servlet class is 'CriteriaServlet'.
Applet "Submit Search Criteria" button code:
private void jButton8ActionPerformed(java.awt.event.ActionEvent evt)
{
criteriaModel.loadCodeBase();
int choice = JOptionPane.showConfirmDialog(this,
"Are you sure you want to submit your search criteria and exit the \"Customise Search Criteria\" web page?",
"Confirm Submit",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (choice == 0)
{
try
{
URL url;
url = new URL(criteriaModel.getCodeBase(), "CriteriaServlet");
System.out.println("Servlet address is: " + url);
// Get the search criteria object.
Object searchSubmitObject = criteriaModel.getObjectSlideData();
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type","application/x-java-serialized-object");
ObjectOutputStream out = new ObjectOutputStream(connection.getOutputStream());
out.writeObject(searchSubmitObject);
out.flush();
out.close();
out.close();
System.out.println("Object Written");
// If this and the corresponding servlet response code is removed
// then the searchSubmitObject fails to be sent.
ObjectInputStream in = new ObjectInputStream(connection.getInputStream());
String response = (String)in.readObject();
System.out.println(response);
in.close();
}
catch (MalformedURLException ex)
{
JOptionPane.showMessageDialog(jPanel8, "Submit criteria file Malformed URL."
+ ex.toString());
System.out.println("MalformedURLException occurred");
Logger.getLogger(CriteriaInterfaceView.class.getName()).log(Level.SEVERE, null, ex);
}
catch (Exception e)
{
System.out.println("Submit criteria file ERROR exception: " + e.toString());
JOptionPane.showMessageDialog(jPanel8, "Submit criteria file ERROR exception:"
+ e.toString());
}
}
// This opens a new page but with a new backing bean with the wrong data.
try
{
appletContext.showDocument(new URL(criteriaModel.getCodeBase()+"MainSearchResult.xhtml"),"_SELF");
}
catch (MalformedURLException ex)
{
Logger.getLogger(CriteriaInterfaceView.class.getName()).log(Level.SEVERE, null, ex);
}
}
I have tried redirecting in the servlet using redirect(url) with no success:
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
{
System.out.println("service(ServletRequest req, ServletResponse res)");
res.setContentType("application/x-java-serialized-object");
try
{
ObjectInputStream in = new ObjectInputStream(req.getInputStream());
slideData = (MultipleSlideDataObject2)in.readObject();
in.close();
if(slideData != null)
{
System.out.println("Serial number of submitted slide series is: " + slideData.getSerialNumber());
}
String temp = "Criteria file Recieved";
ObjectOutputStream outputToApplet = new ObjectOutputStream(res.getOutputStream());
outputToApplet.writeObject(temp);
outputToApplet.flush();
outputToApplet.close();
}
catch (ClassNotFoundException ex)
{
Logger.getLogger(CriteriaServlet.class.getName()).log(Level.SEVERE, null, ex);
}
FacesContext facesContext = FacesUtil.getFacesContext(req, res);
// Get the backing bean.
ProductSelection productSelection = (ProductSelection) facesContext.getApplication().evaluateExpressionGet(facesContext, "#{productSelection}", ProductSelection.class);
productSelection.submitSearchCriteriaFile(slideData);
// This throws an java.lang.IllegalStateException error.
try
{
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext extContext = context.getExternalContext();
String url = extContext.encodeActionURL(context.getApplication().getViewHandler().getActionURL(context, "/MainSearchResult.xhtml"));
extContext.redirect(url);
}
catch (IOException e)
{
throw new FacesException(e);
}
Gives the following error because I suspect the current response has already been committed :
WARNING: StandardWrapperValve[CriteriaServlet]: PWC1406: Servlet.service() for servlet CriteriaServlet threw exception java.lang.IllegalStateException at org.apache.catalina.connector.ResponseFacade.sendRedirect(ResponseFacade.java:522) at com.sun.faces.context.ExternalContextImpl.redirect(ExternalContextImpl.java:572) at searchselection.CriteriaServlet.service(CriteriaServlet.java:217) at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641) at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97) at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185) at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:325) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226) at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165) at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791) at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693) at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954) at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170) at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88) at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76) at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53) at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57) at com.sun.grizzly.ContextTask.run(ContextTask.java:69) at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330) at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309) at java.lang.Thread.run(Thread.java:619)
The return "process_MainSearchResult"; in the backing bean does not work :
public String submitSearchCriteriaFile(MultipleSlideDataObject2 slideData) throws IOException
{
System.out.println("Recieved slide series with serial number: " + slideData.getSerialNumber());
// If there is no slide data then...
if (slideData == null)
{
return "process_MainSearchResultFailed";
}
else
{
rankProducts(slideData);
}
rowStart = 0;
currentStartPage = 0;
currentPageIndex = 0;
calculateNumberPages();
SetupPaginationValues();
// Ignores this...
return "process_MainSearchResult";
}
Faces-config.xml entry:
<navigation-rule>
<navigation-case>
<from-outcome>process_MainSearchResult</from-outcome>
<to-view-id>/MainSearchResult.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
I have also tried this in the backing bean to force a redirect:
FacesContext context = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse)context.getExternalContext().getResponse();
try
{
response.sendRedirect("MainSearchResult.xhtml");
//response.redirect("http://localhost:8080/SearchEngineServer/faces/MainSearchResult.xhtml");
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
and also this in the backing bean:
redirectToPage("/MainSearchResult.xhtml");
Which calls this method:
private void redirectToPage(String toUrl)
{
try
{
FacesContext ctx = FacesContext.getCurrentInstance();
ExternalContext extContext = ctx.getExternalContext();
String url = extContext.encodeActionURL(ctx.getApplication().getViewHandler().getActionURL(ctx, toUrl));
extContext.redirect(url);
}
catch (IOException e)
{
throw new FacesException(e);
}
}
All give the same java.lang.IllegalStateException error as for the servlet example given above. The documentation for redirect states this:
IllegalStateException - if, in a portlet environment, the current response object is a RenderResponse instead of an ActionResponse IllegalStateException - if, in a servlet environment, the current response has already been committed