I am doing validation inside validate() method.
public void validate(){
if(continent.equals("-1")){
HttpServletRequest request=ServletActionContext.getRequest();
HttpSession session=request.getSession();
String s=(String)session.getAttribute("operation");
if(s.equals("edit"))
edit();
else if(s.equals("add"))
add();
addFieldError( "Continent", "Continent must be selected");
}
}
And in jsp(view) added form attribute validate=true
<s:form action="add" name="aaa" cssClass="yy" method="post" validate="true">
<s:textfield name="Code" label="Code" readonly="false" cssClass="defaultTextBox"/>
<s:textfield name="Name" label="Name" cssClass="defaultTextBox"/>
<s:select name="Continent" label="Continent" headerKey="-1" headerValue="Select" list="continentlist" cssClass="defaultTextBox"/>
<s:textfield name="IndepYear" label="Independance Year" cssClass="defaultTextBox" />
<s:submit value="Save" cssClass="login login-submit" theme="simple"/>
</s:form>
But only server side validation is working. My question is -->is it not possible to add client side validation using validate() method?
In Struts 2, Client Side Validation has different meanings, and totally depends on the type of theme you are using.
With XHTML (default) and CSS XHTML, you can use the
Pure JavaScript Client Side Validation
that is totally client side, Javascript based and doesn't communicate with the server.
With the AJAX theme instead, you can run the
AJAX Client Side Validation
that will contact the server, running the whole validation Stack, and (to answer your question) running your validate() methods too.
I personally prefer to use the SIMPLE theme, completely handling the HTML, the CSS and the JavaScript on my own.
Since the server-side validation is mandatory, the client-side validation is to be considered just a surplus, positive for making the page more user-friendly, and to reduce the network traffic in high users environment (you block unsuccessfull - but legit - requests before they go through the wire :)
Consider using HTML5 types with fallback on jQuery, especially if you are targeting the mobile.
actually you shouldn't mix up server side and client side code.
validate method can be invoked only in server side... So there is no way to use this method on client side.
You need to write your own JS side validation as the same as server side validation.
It is possible to perform AJAX validation using your server side code using struts2-jquery plugin , as shown in the Showcase under:
Form Forms with Validation
Form Forms with Custome Validation
The example that might interest you more is Form Submit without AJAX.
Related
For some reasons, I need to create a form with two submit buttons which are going to call different actions after submission.
I found the following example in Multiple Submit Buttons:
<s:form method="post" action="mySubmitAction">
<s:submit value="Submit"/>
<s:submit value="Clear" action="myClearAction"/>
</form>
As my project is using Struts 2.3.16.3, struts.mapper.action.prefix.enabled = true is needed.
However, is there any risk to enable it back in struts 2.3.16.3?
Will it share the same security problem in 2.3.15.2?
If yes, would you mind providing some alternatives to make the multiple submit buttons work on single form? if-else solution is not preferred.
The vulnerabilities discovered in versions Struts 2.0.0 - Struts 2.3.15.2 related to the OGNL injection attack. In fact the action: prefix opens a door for this kind of attacks.
Previously it's discovered in S2-016, the fixed version was 2.3.15.1. Lately S2-018 was introduced and they disabled the action: prefix. Recommended upgrade was 2.3.15.3.
This means that using action: prefix is discouraged and you can enable in on your own risk. In S2-019 the DMI was disabled by default too, so you can't use method: prefix because it works only if DMI is enabled.
These restrictions made side effect on multiple button usage where action or method attributes used to bind s:submit buttons to the action other than in the s:form action attribute. To use multiple buttons to execute its own methods of the action class you can pass a parameter that holds a method name. It could be a hidden field or submit field, etc.
When execute method is called this information should be already available and you can use Java to call the method by the name. Another approach is most popular to use javascript to modify the form's action attribute in the onclick event handler before the form is submitted.
<s:form name="myForm" method="post" action="mySubmitAction" >
<s:submit value="Submit"/>
<s:submit value="Clear" onclick="myClearAction()"/>
</form>
<script>
function myClearAction(){
document.forms["myForm"].action = "<s:url action='myClearAction' />";
}
</script>
Could you help me to come up with solution.
There are JSP-page which sends form parameters to servlet.
Usually I parse parameters by HttpServletRequest.getParameter() which works fine for forms with tiny parameter numbers.
Now I'm developing application which has a lot of JSPs with number of parameters and the standard way of form processing is inconvenient.
I think that possible solution might be by using -action.
I don't understand whether it works for me.
I browsed a lot of materials but find nothing about it.
I mean that there is any information regarding possibility to get form parameters in jsp by ,
automatically create instance of the entity class,
map all the parameters to entity-properties and send the entity-instance to the servlet.
Please take a look at the code:
index.jsp
<html>
<head>
<title></title>
</head>
<body>
<form method="post" action="NewFormServlet" enctype="application/x-www-form-urlencoded">
<jsp:useBean id="client-bean" class="model.entity.Client" scope="request"/>
<h3>Please enter client information</h3><br>
Client first name<input type="text" name="first-name"/><br>
<jsp:setProperty name="client-bean" property="firstName" value="${requestScope.first-name}"/>
Client last name<input type="text" name="last-name"/><br>
<jsp:setProperty name="client-bean" property="lastName" value="${requestScope.last-name}"/>
Client address<input type="text" name="address" size="100"/><br>
<jsp:setProperty name="client-bean" property="address" value="${requestScope.address}"/>
Client city<input type="text" name="city"/><br>
<jsp:setProperty name="client-bean" property="city" param="${requestScope.city}"/>
Client postal code<input type="text" name="postal-code"><br>
<jsp:setProperty name="client-bean" property="postalCode" value="${requestScope.postal-code}"/>
<input type="hidden" name="jsp-identifier" value="client-form">
<input type="submit" value="Submit">
</form>
</body>
</html>
What is incorrect in this code? Thank you in advance.
You should first think about what occurs on server and what occurs in browser, as well as what is transmitted via HTTP. A form submission uses many phases :
on server : the JSP is executed using servlet context, session, and request attributes, with still full access at the previous request (parameters, ...) => all that generates a HTML page (with eventually css or javascript linked or included)
on browser : the browser gets and parses the HTML page, optionnaly gets linked resources (images, etc.), and display the form to the user
on browser : the user fills the input fields of the form and clicks the input button
on browser : the browser collates data form input fields, generate an new HTTP request (usually a POST one) and sends it to server
on server : the servlet container pre-processes the request (until that is is only a stream of bytes conforming to HTTP protocol) and calls the appropriate servlet method with a new HttpServletRequest reflecting current HTTP request, and a HttpServletResponse to prepare what will be sent back to browser after processing
All that means that anything you can do to request attributes in the JSP part will be lost at the time of processing of the submitted form by the servlet. You can only rely on session attributes, and on input form fields that will be accessible as request parameters.
So with your current JSP, the Servlet will find nothing in request attributes (it is a different HttpServletRequest) and will only be able to use parameters with names firstName, lastName, address, city, etc.
I can understand it is not the expected answer, but HTTP protocol is like that ...
EDIT per comment :
You can put the attribute in session, and then the servlet will use the same session as the JSP. But read again what I wrote above and think when things happen :
on server, when executing the JSP, you create an empty Client bean that you put in session scope, and use its value to initialize the form fields. Stop for the server part
on client, user fills the input fields - the server knows nothing on that - and submit the form through a new request
on server, the servlet has the values in request parameters, but the session still contains the previous values and so the Client bean has null values
I'm sorry but there's not enough magic for the server to automatically find in its attributes (either request or session) what comes from form submission : it only exists in request parameters, and it is the servlet job to process them and eventually put them in attributes.
Edit:
It appears that jsp:useBean is an old school way to collect up a group of parameter values for easier display on a page.
It does not add an attribute when the request is posted.
Based on that,
I see little value in the jsp:useBean tag,
since you can use el expressions to access attributes that you set in a servlet.
This does not help you get the posted parameter values into a bean in the servlet.
You can write a method on the bean to extract the parameter values from the request (visitor pattern).
For example:
class bean
{
private String value;
public void loadFromHttpServletRequest(final HttpServletRequest request)
{
value = request.getParameter("value");
}
}
Consider using a package like spring-mvc.
I'm implementing a JSP which expects a few parameters which have to be validated before running the jsp.
Suggestion: Validate the parameters inside the JSP using
Taglibraries
Suggestion: Pre-parse the Parameters in a Filter
What do you think?
Edit
Thank you for the good answers, but I was wondering what would be the best practice in case you are offering a service like google chart API where you can't expect that the parameters are checked by a form before they are sent.
example:
https://chart.googleapis.com/chart?cht=&chd=&chs=&...additional_parameters...
None of both are good approaches. Controller/business logic doesn't belong in a JSP (tag). A filter is almost good, but it's not specific enough. This job should be done by a servlet. You're submitting the form to a servlet to postprocess it, right? It sounds like that you're not already doing that, the answer would otherwise have been pretty straightforward.
In our servlets tag wiki page you can find a hello world example of a good approach of using a JSP with a Servlet to postprocess a form submit. Here's an extract of relevance:
<input id="name" name="name" value="${fn:escapeXml(param.name)}">
<span class="error">${messages.name}</span>
with
String name = request.getParameter("name");
if (name == null || name.trim().isEmpty()) {
messages.put("name", "Please enter name");
}
// ...
request.getRequestDispatcher("/WEB-INF/hello.jsp").forward(request, response);
Further, there exist MVC frameworks which removes all the boilerplate (duplicated/repeated) servlet code for this kind of use cases, such as JSF, Spring MVC, Wicket, Stripes, Struts2, etc. With for example JSF it look just something like this:
<h:inputText id="name" value="#{bean.name}" required="true" requiredMessage="Please enter name" />
<h:message for="name" />
That's all. The JSF's FacesServlet controller servlet will validate if it's been filled in and display a (configureable) message at the given location, without any need for custom Java code. You could even move it to the model, JSF has transparent support for JSR303 bean validation as well. E.g.
<h:inputText id="name" value="#{bean.name}" />
<h:message for="name" />
with
#NotNull(message="Please enter name")
private String name;
Update as per your edit:
Thank you for the good answers, but I was wondering what would be the best practice in case you are offering a service like google chart API where you can't expect that the parameters are checked by a form before they are sent. example: https://chart.googleapis.com/chart?cht=&chd=&chs=&...additional_parameters...
Just use a servlet the same way. The only difference is that you've to implement the job in doGet() instead of doPost() and if necessary return HTTP 400 on an error :) Once again, check our servlets tag wiki page to understand their purpose better. Or to go a step further, use a webservice framework instead, such as JAX-WS or JAX-RS which do this job transparently like a MVC framework does for HTML pages.
Use an MVC Framework (Spring MVC, Stripes, Struts 2 etc.) and validate the parameters in the controller class. Every MVC framework supports parameter validation, and you get a clean separation of concerns.
Example: Spring MVC automatically registers JSR-303-style parameter Validation (if you have a JSR-303 provider, e.g. Hibernate-Validator, on the classpath) when using mvc:annotation-driven
Some background: I am building a custom JSF component. The component is basically a text editor and it should have a "Save" -button for saving the content string of the editor. As I am using the CodeMirror library, I need to fetch the content (string) from the editor with javascript and send that to the server. Therefore, in this case I cannot use XML-based JS invocation such as f:ajax.
The question: I was planning to send the string with jsf.ajax.request, but it doesn't directly support calling methods on beans. How can I invoke a method in a bean with JSF in AJAX manner?
There at least two ways to get around this:
Include a hidden form to page with hidden inputfield. Update that inputfield from javascript and then call jsf.ajax.request to post that form. Custom actions can be invoced in the property's getter or setter if needed.
Do the request with raw XMLHttpRequest (or maybe with help from some other JS library). Create a servlet and call that.
Both ways are clumsy and the latter also breaks out of JSF scope.
Am I missing something? How do you do these?
There is a quite similar question, but the answers given only refer to XML-based AJAX invocations. There is also another similar question, but that refers to XML-based AJAX calls as well.
I couldn't find out how to call beans direcly with javascript, but here is a hack around calling f:ajax-declaration from javascript:
1) Create a hidden form with fields for all the data that you want to send to the server. Include a h:commandButton as well:
<h:form id="hiddenForm" style="display: none;">
<h:inputHidden id="someData" value="#{someBean.someData}" />
<h:commandButton id="invisibleClickTarget">
<f:ajax execute="#form" listener="#{someBean.myCoolActionOnServer()}" />
</h:commandButton>
</h:form>
As usual, listener attribute, #{someBean.myCoolActionOnServer()} in this case, refers to the method that you want to execute on the server.
2) In some other button use onclick to call for your special javascript AND click the trigger-button via javascript:
<h:commandButton value="Click me" onclick="populateTheForm('hiddenForm'); document.getElementById('hiddenForm:invisibleClickTarget').click(); return false;" />
populateTheForm() should actually fill the data into hiddenForm's fields.
This is a simplification of my case but should work. Still looking for more conventient approach, though.
I did this task several times. Yo don't need multiply hidden fiels. You can use only one hidden field, convert all input values to JSON object via JSON.stringify and set into this field. On the server side - deserialize JSON object (there are many Java libs for that) to an Java class. That's all.
Suppose an example. I have following interface:
public interface DataSource<T> {
Future<T> fetch();
}
This datasource can do asynchronous data fetching. And we have following tag for using datasource in JSP:
<html>
<d:fetch from="${orderDS}" var="orders">
<c:foreach in="${orders}" var="order">
<div class="order">
<c:out value="${order.title}" />
</div>
</c:foreach>
</d:fetch>
</html>
So, what I want? I want JSP rendering engine to call my custom tag (FetchTag in this example) twice. On first call FetchTag will do DataSource.fetch() call and save Future locally as a object field. On second call FetchTag do Future.get() call and will be blocked until data becomes available.
Is there any way to do such a thing?
I think a better design would not try to alter JSP rendering. Put all that database code on the server side, where it belongs, and use an AJAX call to get that data from a server-side component.
In general, I've found that embedding stuff in custom tag libraries is a bad idea. JSTL and/or Spring tag libraries are all that I need. If I feel like my UI needs to do more, I'm thinking about it incorrectly.
For JS disabled clients, I'd just make them do the round trip for the data and not try to do it in the background. Give them a choice: wait or turn on JS.