How can I call a specific method in a class using this tag?
<jsp:useBean id="user" scope="??" class="com.example.User" type="com.example.User" />
Assuming your bean User has a method called getName()
<jsp:useBean id="user" scope="request" class="com.example.User" />
// ...
<h1>Hello <jsp:getProperty name="user" property="name" /></h1>
The scope could be something else than request : depends on what you want (session, page, etc)
EDIT: your second question was about calling a business method in your jsp
The fact is, you should not call business method into your JSPs. Your JSP pages should only display static (html, etc) and dynamic (beans for example) content. If you follow MVC pattern, business job is delegated to servlets. Your JSPs are only simple views (reading properties of beans) and are forbidden (in directory WEB-INF).
For your JSP pages, proceed as following:
Action of html form is your servlet controller (method POST)
Add hidden input to help servlet recognize what to do: <input
type="hidden" name="action" value="update" /> or <input
type="hidden" name="action" value="register" />
You can also display dynamic content (beans). For that, you should consider using JSTL.
Example (servlet sends an ArrayList of Movie beans on request scope):
<c:forEach items="${requestScope.results}" var="movie">
// ${movie.title}
// etc
</c:forEach>
For your servlet controller, proceed as following:
In doPost method (because we're using POST method in html form), you can dispatch business logic depending on action received: request.getParameter("action")
If action is update, then we perform update business logic.
If action is register, then we perform register business logic.
etc ...
Now, we can store some data in request scope to communicate to jsp page:
ArrayList<Movie> results = new ArrayList<Movie>();
results.add(new Movie(...));
// etc...
request.setAttribute("results", results);
And finally, send data and display jsp:
request.getRequestDispatcher("/WEB-INF/update.jsp").forward(request, response);
An example of web.xml (with a servlet mapped as welcome file index.jsp)
<servlet>
<servlet-name>Search</servlet-name>
<servlet-class>Servlets.Search</servlet-class>
</servlet>
<servlet>
<servlet-name>Register</servlet-name>
<servlet-class>Servlets.Register</servlet-class>
</servlet>
<servlet>
<servlet-name>Update</servlet-name>
<servlet-class>Servlets.Update</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Search</servlet-name>
<url-pattern>/index.jsp</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Register</servlet-name>
<url-pattern>/Register.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Update</servlet-name>
<url-pattern>/Update.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<jsp:useBean id="user" scope="request" class="com.example.User" type="com.example.User" />
<jsp:setProperty name="user" property="*" />
<c:set var="saveStatus" value="${user.save()}" />
Related
I have a main file (main.jsp) which includes multiple other JSPs.
I've added some servlet mapping to main.jsp to change the url from:
folder/appname/main.jsp
to:
appname/
Here is my web.xml:
<servlet>
<servlet-name>Main</servlet-name>
<jsp-file>/folder/appname/main.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>Main</servlet-name>
<url-pattern>/appname/</url-pattern>
</servlet-mapping>
The problem however, is that when I load this page i get the following error
java.io.FileNotFoundException: /page_modules/included_file.jsp
The file above is included in the main.jsp like so:
<jsp:include page="page_modules/included_file.jsp" />
Folder structure as requested:
Dynamic Web Project
>Java Resources
>src
>com.project
>servlet
>WebContent
>forms
>folder
main.jsp
>page_modules
included_file.jsp
Try using code like
<jsp:include page="/page_modules/included_file.jsp" />
Or
<jsp:include page="/forms/folder/page_modules/included_file.jsp" />
This question already has answers here:
What causes "java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute"?
(7 answers)
Closed 6 years ago.
I am beginner to Spring MVC Framework. I started to learn Spring two days back. For learning purpose I am developing one simple Application. i.e., Get user input from form and display values in another page. I got an Exception " java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute". I cant figure out what's wrong in my code. I searched Google and tried many solution but the problem is still here.
Here is my view
index.jsp
<form:form action="/addDisplay" method="POST">
<form:label path="name"><h3>Name</h3></form:label>
<form:input type="text" path="name" cssClass="form-control text-center" required="required"/>
<form:label path="age"><h3>Age</h3></form:label>
<form:input type="number" path="age" cssClass="form-control text-center" required="required"/>
<form:label path="work"><h3>Work Place</h3></form:label>
<form:input type="text" path="work" cssClass="form-control text-center" required="required"/>
<form:label path="designation"><h3>Designation</h3></form:label>
<form:input type="text" path="designation" cssClass="form-control text-center" required="required"/>
<form:label path="area"><h3>Area</h3></form:label>
<form:input type="text" path="area" placeholder="Where Are You From?" cssClass="form-control text-center" required="required"/>
<form:label path="mobile"><h3>Mobile Number</h3></form:label>
<form:input type="number" path="mobile" placeholder="Your Mobile Number.!" cssClass="form-control text-center" required="required"/>
<form:label path="email"><h3>Email</h3></form:label>
<form:input type="email" path="email" placeholder="Your Email Id..!" cssClass="form-control text-center" required="required"/>
<br/>
<input type="submit" value="Generate" class="btn btn-success form-control"/>
</form:form>
myself.jsp
<div style="margin-top: 3%; font-size: 20px;">
<h3>My Introduction.</h3>
<p>
Hi, I am ${name} my age is ${age} and I am from ${area}. I am working as a ${designation}
in ${work}. You can contact me in my mobile ${mobile} and You can also shoot mail to
${email}.
</p>
</div>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>SpringWork</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
</web-app>
mvc-dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.infofaces.spring.form" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="com/infofaces/spring/form/MySelf" />
</bean>
<mvc:resources mapping="/resources/**" location="/resources/" />
<mvc:annotation-driven />
</beans>
My model name is Myself.java and it has private variables and getter, setter methods for that variable. Here is my controller.
HelloController.java
package com.infofaces.spring.form;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class HelloController {
#RequestMapping(value = "/display", method = RequestMethod.GET)
public ModelAndView display() {
return new ModelAndView("myself", "command", new MySelf());
}
#RequestMapping(value="/addDisplay", method = RequestMethod.POST)
public String addDisplay(#ModelAttribute("command") MySelf myself, ModelMap model) {
model.addAttribute("name",myself.getName());
model.addAttribute("age", myself.getAge());
model.addAttribute("work", myself.getWork());
model.addAttribute("designation", myself.getDesignation());
model.addAttribute("mobile", myself.getMobile());
model.addAttribute("email", myself.getEmail());
return "myself";
}
}
Full Stack Trace.
type Exception report
message java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute
description The server encountered an internal error that prevented it from fulfilling this request.
exception
org.apache.jasper.JasperException: java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute
org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:549)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:465)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:395)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:339)
javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
root cause
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute
org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:141)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getBindStatus(AbstractDataBoundFormElementTag.java:179)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getPropertyPath(AbstractDataBoundFormElementTag.java:199)
org.springframework.web.servlet.tags.form.LabelTag.autogenerateFor(LabelTag.java:130)
org.springframework.web.servlet.tags.form.LabelTag.resolveFor(LabelTag.java:120)
org.springframework.web.servlet.tags.form.LabelTag.writeTagContent(LabelTag.java:90)
org.springframework.web.servlet.tags.form.AbstractFormTag.doStartTagInternal(AbstractFormTag.java:103)
org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag(RequestContextAwareTag.java:80)
org.apache.jsp.index_jsp._jspx_meth_form_005flabel_005f0(index_jsp.java:265)
org.apache.jsp.index_jsp._jspx_meth_form_005fform_005f0(index_jsp.java:170)
org.apache.jsp.index_jsp._jspService(index_jsp.java:105)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:395)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:339)
javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
Please help to find problem in my code. Thanks in advance.
You are missing commandName="command" in your index.jsp file .
<form:form action="/addDisplay" method="POST" commandName="command" >
Make sure that command object is available in your request attribute before index.jsp is being processed. I hope this would work.
EDIT : As you said in comment when you call index.jsp definatily you will get java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute error.
Because when your jsp is being rendered command object not available for that first you have to make request to controller , put object into Model name it command and then provide view name index.jsp
For example :
#RequestMapping(value = "/index", method = RequestMethod.GET)
public ModelAndView display() {
return new ModelAndView("index", "command", new MySelf());
}
Now you won't get that error. I hope this would work.
Instead of forwarding to your index.jsp via welcome-files list, you should add
<mvc:view-controller path="/" view-name="index"/>
to your mvc configuration, and an accompanying controller mapping where you will add the command object to the model, e.g.
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Model model) {
model.addAttribute("command", new MySelf());
return "index";
}
Your problem is that you got forwarded to the index.jsp via welcome-files and the request wasn't process by spring. Yet you use spring's form:form which if not otherwise renamed via commandName or modelAttribute attributes expects an object with the key command inside the request attributes
you have used spring form tag in index.jsp where a command/modelAttribute object should be available as a request parameter to bind form data, which is you have not done and the exception message what it says.
To solve this problem follow below steps:
Step 1:
Remove all welcome-file-list from web.xml.
Step 2:
add "/" into display GET handler.
#RequestMapping(value = {"/", "/display"}, method = RequestMethod.GET)
public ModelAndView display() {
return new ModelAndView("myself", "command", new MySelf());
}
Step 3:
add modelAttribute name in form tag:
<form:form action="${pageContext.request.contextPath}/addDisplay"
method="POST"
modelAttribute="command">
Consider, you have HTML form like below
Login Form:
<%#taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<body>
<form:form action="doLogin.html" method="post" modelAttribute="loginEntity" name="loginForm">
<!-- Form inputs -->
</form:form>
</body>
</html>
You want to perform login by calling action doLogin.html. As you have specified modelAttribute="loginEntity" attribute in Spring form which is created using above code snippet. You must set an empty Object of model which hold required request params in Controller. Observe below code carefully:-
Model Class:
public class Login {
private String userName = "";
private String password = "";
// getters/setters
}
Controller Class:
#Controller
public class LoginController {
#RequestMapping(value = "/showLoginForm", method = RequestMethod.GET)
public ModelAndView showLoginForm() {
System.out.println("In login form...");
ModelAndView mv = new ModelAndView("login");
mv.addObject("loginEntity", new Login());
return mv;
}
#RequestMapping(value = "/doLogin", method = RequestMethod.POST)
public ModelAndView doLogin(#ModelAttribute Login login, BindingResult result) {
String userName = login.getUserName();
String password = login.getPassword();
if ("OO7".equals(userName) && "OO7".equals(password)) {
return new ModelAndView("forward:success.html");
} else {
return new ModelAndView("forward:failure.html");
}
}
}
In the controller, I have added an empty model new Login() for the modelAttribute loginEntity in the showLoginForm() function. This will map all the request parameters & allow to set &/or retrieve values from them.
Now, you can add link to your index.jsp which will give a call to Controller to display login.jsp just like below :-
Index Page:
<html>
<body>
<ul>
<li>Login</li>
</ul>
</body>
</html>
Overall Request Flow:
At application start index.jsp will load having a link to login.jsp.
On click of link Login a call to controller is made & it searches for request mapping showLoginForm in it.
Once he found the specified mapping, he proceed further to display login.jsp page.
On submit of the login form, a request for doLogin.html is made. Once again control goes to Controller to search for doLogin request mapping.
Once he found doLogin request mapping, depending on the login credentials, you will be redirected to either success.jsp or failure.jsp page.
NOTE:
Don't mix commandName & modelAttribute in Spring form. You are only allow to use any of them.
If you forgot to add empty model in the Controller, then you will face below exception
java.lang.IllegalStateException: Neither BindingResult nor plain target object for
bean name 'loginEntity' available as request attribute
I hope this will clear your idea of using #ModelAttribute in Spring.
I have some rest services running already, using cxf-rt-frontend-jaxrs 2.7.7
/myservice/customers
/myservice/items
My rest service provides 2 endpoints:
#Component
public class CustomerService {
#GET
#Path("customers")
#Produces({MediaType.APPLICATION_JSON})
public ... getCustomers() { ... }
#GET
#Path("items")
#Produces({MediaType.APPLICATION_JSON})
public ... getItems() { ... }
}
This works great, and now I would like to add some jsp pages.
I've read about Redirecting requests and serving static content, but I can't get it to work and I am confused about the configuration in the web.xml and applicationContext.xml.
Here's what I have so far:
web.xml
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
applicationContext.xml
<jaxrs:server id="rest" address="/">
<jaxrs:serviceBeans>
<ref bean="customerWebService" />
</jaxrs:serviceBeans>
<jaxrs:providers>
<bean class="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider"/>
<ref bean="dispatchProvider"/>
</jaxrs:providers>
</jaxrs:server>
<bean id="dispatchProvider" class="org.apache.cxf.jaxrs.provider.RequestDispatcherProvider">
<property name="dispatcherName" value="jsp"/>
<property name="resourcePath" value="/admin/item.jsp"/>
<property name="beanNames">
<map>
<entry key="com.company.domain.Item" value="item"/>
</map>
</property>
</bean>
jsp page
I have put a jsp web page named item.jsp into webapp/WEB-INF.
<%# page import="com.company.domain.Item" %>
<%
Item item = (Item) request.getAttribute("item");
%>
<html>
<head></head>
<body>
Item: <%= item.getEnglishName() %>.
</body>
</html>
Errors
If I open /customerservice/items I receive a valid JSON response from the rest service.
However if I open /customerservice/admin/item.jsp I receive this:
[10:34:45.791] [qtp104543434-33] WARN JAXRSUtils - No operation matching request path "/customerservice/admin/item.jsp" is found, Relative Path: /admin/item.jsp, HTTP Method: GET, ContentType: /, Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8,. Please enable FINE/TRACE log level for more details.
[10:34:45.796] [qtp104543434-33] ERROR DefaultExceptionMapper - DefaultExceptionMapper returned response: Internal Server Error
javax.ws.rs.ClientErrorException: null
at org.apache.cxf.jaxrs.utils.JAXRSUtils.findTargetMethod(JAXRSUtils.java:503) ~[cxf-rt-frontend-jaxrs-2.7.7.jar:2.7.7]
at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:227) ~[cxf-rt-frontend-jaxrs-2.7.7.jar:2.7.7]
at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAXRSInInterceptor.java:103) ~[cxf-rt-frontend-jaxrs-2.7.7.jar:2.7.7]
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272) [cxf-api-2.7.7.jar:2.7.7]
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) [cxf-api-2.7.7.jar:2.7.7]
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:239) [cxf-rt-transports-http-2.7.7.jar:2.7.7]
at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:248) [cxf-rt-transports-http-2.7.7.jar:2.7.7]
at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:222) [cxf-rt-transports-http-2.7.7.jar:2.7.7]
at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:153) [cxf-rt-transports-http-2.7.7.jar:2.7.7]
What am I doing wrong?
Do I need separate servlets and url-mappings in my web.xml?
Does my request dispatcher require furhter configuration (e.g. dispatcherName property) ?
Many thanks for any guidance.
I changed my CXFServlet url-pattern to /rest/*
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
My rest urls are now /customerservice/rest/items and /customerservice/rest/customers.
And now I get a response for url /customerservice/admin/item.jsp, when my jsp pages are placed under webapp/admin (not webapp/WEB-INF/admin), which I presume is correct.
It appears that the request "falls through" to a default apache jasper JspServlet (which I have not configured in any way).
The response:
Hello World.
Great, thanks to Lutz for the initial comment!
Now I need to inject some beans into the jsp pages, perhaps there is there something like exposeContextBeansAsAttributes that I can use here.
When creating portlet in Liferay IDE, I have configured it to have Liferay's configuration mode. In response, the wizart created JSP file with the following text:
<%# taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<portlet:defineObjects />
This is the <b>MyPortlet</b> portlet in Config mode.
How to call this page from Liferay to see this text? When clicking wrench icon and selecting Configuration I see nothing similar.
UPDATE
Path is set correctly because it was set by wizard.
The question is how to call this JSP from web interface by a mouse?
Usually the problem is that the path to the configuration jsp is not properly set.
In portlet.xml
Add the following:
<init-param>
<name>config-template</name>
<value>/path/to/configuration.jsp</value>
</init-param>
as a child of the <portlet> element that corresponds to the portlet you're trying to modify.
Your final portlet.xml should look something like:
<portlet-app>
<portlet>
<portlet-name>my-portlet</portlet-name>
<display-name>My Portlet</display-name>
<portlet-class>com.liferay.portlet.StrutsPortlet</portlet-class>
<init-param>
<name>config-template</name>
<value>/path/to/configuration.jsp</value>
</init-param>
<init-param>
<name>view-action</name>
<value>/my_portlet/view</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
</supports>
</portlet>
</portlet-app>
From the wiki (no shame here though, took me a very long time to find it):
Add Config Page to Plugin Portlet <- get more info here
liferay-portlet.xml->
<portlet>
<portlet-name>configuration-example</portlet-name>
<icon>/icon.png</icon>
<configuration-action-class>com.sample.jsp.action.ConfigurationActionImpl</configuration-action-class>
<instanceable>true</instanceable>
<header-portlet-css>/css/test.css</header-portlet-css>
<footer-portlet-javascript>/js/test.js</footer-portlet-javascript>
</portlet>
ConfigurationActionImpl.java (or your class)->
public class ConfigurationActionImpl implements ConfigurationAction {
public void processAction(PortletConfig config, ActionRequest actionRequest, ActionResponse actionResponse) throws Exception {
String portletResource = ParamUtil.getString(actionRequest, "portletResource");
PortletPreferences prefs = PortletPreferencesFactoryUtil.getPortletSetup(actionRequest, portletResource);
//Read, validate, and then set form parameters as portlet preferences
prefs.store();
SessionMessages.add(actionRequest, portletConfig.getPortletName() + ".doConfigure");
}
public String render(PortletConfig config, RenderRequest renderRequest, RenderResponse renderResponse) throws Exception {
return "/configuration.jsp";
}
}
Configuration.jsp
<%# taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<%# taglib uri="http://liferay.com/tld/portlet" prefix="liferay-portlet" %>
<portlet:defineObjects />
<form action="<liferay-portlet:actionURL portletConfiguration="true" />" method="post" name="<portlet:namespace />fm"> <input name="<portlet:namespace /><%=Constants.CMD%>" type="hidden" value="<%=Constants.UPDATE%>" />
Type: <select name="<portlet:namespace />type"> <option value="casual">Casual</option> <option value="formal">Formal</option> </select> <br/>
<input type="button" value="Save" onClick="submitForm(document.<portlet:namespace />fm);" /> </form>
"Note the portletConfiguration attribute in the liferay-portlet:actionURL tag."
I'm using form based authentication.
I have a logout link which looks like:
<h:commandLink action="#{loginBean.logout}">
<h:outputText value="logout" />
</h:commandLink></div>
And the corresponding logout method:
public String logout() {
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
return "/view/index?faces-redirect=true"; // Redirect added as per BalusC's suggestion.
}
After hitting the logout link I'm returned to the front page, but seemingly without CSS. When I hit a button to run a search I get the following error:
javax.faces.application.ViewExpiredException: viewId:/view/index.jsf - View /view/index.jsf could not be restored.
And yet the CSS is actually under /resources which shouldn't require authentication as I understand my web.xml:
<security-constraint>
<web-resource-collection>
<web-resource-name>fizio</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Unprotected area</web-resource-name>
<url-pattern>/resources/*</url-pattern>
</web-resource-collection>
</security-constraint>
From this state I seem to be able to login again and see some data between occasional view-could-not-be-restored errors, but no CSS. It's all a bit broken really. Any suggestions would be appreciated.
ETA: Login form:
<form method="POST" action="j_security_check">
<label for="j_password">Username:</label> <input type="text" name="j_username" />
<br />
<label for="j_password">Password:</label> <input type="password" name="j_password" /> <input type="submit" value="Login" />
</form>
You need to redirect after invalidate. Otherwise the page is been shown in midst of the "invalidated" session. Add faces-redirect=true to the outcome to trigger the redirect.
public String logout() {
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
return "/index?faces-redirect=true";
}
The redirect will cause the webbrowser to fire a new GET request after the POST response and in turn cause the server to create a brand new session. This way the views will work as intended.
As to the CSS resources, they apparently still need a login. The "Unprotected area" constraint which you have there is not going to work. Remove it and change the URL-pattern of your main security constraint to for example /app/* or whatever a common path of the secured area is.