Suppose I have a bean which has lets say 10 properties.
Also I have a error onject which has three propertes viz. errorFlag, errCd, and errMsg
And I want to validate that bean properties sequentialy and I want to break on first occcurence of error and populate the error object.
How can I do that, I want to have minimum If. else if statements.
ErrorObj Bean
public class ErrObj{
private String errorMessage;
private String errorCode;
private boolean errorFlag;
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public boolean isErrorFlag() {
return errorFlag;
}
public void setErrorFlag(boolean errorFlag) {
this.errorFlag = errorFlag;
}
}
Below is the class where I am validating the Bean
Assume, im using some static methods of Custom util class which return boolean depending upon if a field is valid or not.
public class ValidateMyBean{
ErrObj errObj = new ErrObj();
if(!CustomUtils.isValid(myBean.getProp1))
{
// set some error conditions
errObj.errorCode("123");
errobj.setErrorMessage("validation 1 Failed");
}
else if(!CustomUtils.isValid(myBean.getProp2))
{
}
..........so on
}
So, if my bean has 10 properties and I have to validate each property against lets say 3 validator methods, I don't want to write multiple "if - elseif" statements or write mutliple "if" statements with return statement at the end of each if statement, in case of any error.
Is there any cleanser way or there are some frameworks which can help me reach the desired result?
PS:This Java application is using Spring Core framework and is a webservice application and not a MVC application.
There are many validation utils. You can check this example:
Spring MVC: How to perform validation?
There is also a jsr spec about it: JSR-303
http://beanvalidation.org/1.0/spec/
Enjoy
Accessing Java Beans using JSP:
Using JSP writing a java bean program becomes more easier.
The useBean action declares a JavaBean for use in a JSP. Once declared, the bean becomes a scripting variable that can be accessed by both scripting elements and other custom tags used in the JSP. The full syntax for the useBean tag is as follows:
<jsp:useBean id="bean's name" scope="bean's scope" typeSpec/>
Here values for the scope attribute could be page, request, session or application based on your requirement. The value of the id attribute may be any value as a long as it is a unique name among other useBean declarations in the same JSP.
Following example shows its simple usage:
<html>
<head>
<title>useBean Example</title>
</head>
<body>
<jsp:useBean id="date" class="java.util.Date" />
<p>The date/time is <%= date %>
</body>
</html>
This would produce following result:
The date/time is Thu Sep 30 11:18:11 GST 2010
Related
In my java code
package com.luv2code.jsp.tagdemo;
public class Student {
public String firstName;
public String lastName;
public boolean goldCustomer;
public Student(String firstName, String lastName, boolean goldCustomer) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.goldCustomer = goldCustomer;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public boolean isGoldCustomer() {
return goldCustomer;
}
public void setGoldCustomer(boolean goldCustomer) {
this.goldCustomer = goldCustomer;
}
}
In JSP Code
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%# page import="java.util.*,com.luv2code.jsp.tagdemo.Student" %>
<%
ArrayList<Student> data=new ArrayList<>();
data.add(new Student("Subhajit","Maity",true));
data.add(new Student("Biswajit","Kundu",true));
data.add(new Student("Sourav","Das",false));
pageContext.setAttribute("myStudent", data);
%>
<html>
<head>
</head>
<body>
<c:forEach var="tempStudent" items="${myStudent}">
${tempStudent.firstName}
</c:forEach>
</body>
</html>
If I use getter and setter method for setting and getting the firstname,lastname and goldcustomer then the code works fine.But with out getter and setter it gives error.If I declare the class variable as public then it can be accessible to any where then ahy should I use getter and setter menthod?
JSP/Servlet engine was designed to work following some basic principles. Among those principles is Encapsulation, which you should never give direct access to your class properties.
When your jsp is compiled the EL expression ${tempStudent.firstName} will look like com.luv2code.jsp.tagdemo.Student.getFirstName() assuming you are following encapsulation principle.
That's is part of spec, you cannot change this behavior.
The getter and setter are good tools for encapsulation. These methods may contain some logic besides their main purpose. You might want to get to check privileges whether the getter and setter should be executable, also, you might want to do some different things. For instance, if you set a husband's family name, you might need to also set the family name of the individual. You are not able to do this if you simply set the values of public data members.
You need to follow encapsulation rules for using JSP Pages. In your jsp you can call anything that start with get.
public String getAnyString() {
return "Any String";
}
You can call it to your JSP page. It doesn't look for you variables it will go for you encapsulated methods.
For readable properties there will be a getter method to read the
property value. For writable properties there will be a setter method
to allow the property value to be updated. Thus even when a script
writer types in something such as “b.Label = foo” there is still a
method call into the target object to set the property, and the target
object has full programmatic control. So properties need not just be
simple data fields, they can actually be computed values. Updates may
have various programmatic side effects
From java doc Beans
Your JSP page uses two several languages (besides HTML and JSP tags).
1 - Java
The code close to the top is regular Java:
ArrayList<Student> data=new ArrayList<>();
data.add(new Student("Subhajit","Maity",true));
If you wanted to, you could access the fields directly, i.e. without getter and setter methods:
Student student = ...;
student.lastName = "Maity";
2 - Expression Language
Tags such as <c:forEach items="${myStudent}"> and expressions such as ${tempStudent.firstName} do not use Java but the Expression Language of Java EE. It is designed as a simple scripting language.
As per specification, the expression ${tempStudent.firstName} accesses the property firstName of the JavaBean tempStudent. A JavaBean is basically any Java object that conforms to certain rules. In particular, getter and setter methods becomes properties.
As per JavaBeans Specification, chapter 7.1:
Properties are always accessed via method calls on their owning
object.
That's why it doesn't work with fields only but requires getters and possibly setters.
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.
Anybody know why my form does not bind
Here is what I have
public class Account {
#Required
private String id = "";
...
}
a form in controlers.Application.java
static Form<Account> accountForm = Form.form(Account.class);
with a method
public static Result addAccount() {
Form<Account> filledForm = accountForm.bindFromRequest();
if (filledForm.hasErrors()) {
...
...
and a scala form template:
#form(action = routes.Application.addAccount()) {
#inputText(accountForm("id"))
<input type="submit" name="action" value="submit ID"/><br />
}
oh and routes line defined as:
GET /createAccount controllers.Application.addAccount()
I printed the data received and it gets the id value and the action submit.
I have printed all validation errors and it seems to be on the id field it just says error.required
don't know cause the address line I am typing in is:
/createAccount?id=1001&action=submit+ID
but the if statement hasErrors() always results to true
Please - is there something obvious I am missing?
When your bean has private fields you need to define proper java bean getters and setters (the binding is done by SpringDataBinder which needs this).
First of all I'm newbie in Struts.
I've a class:
public class Articulo {
private int codigo;
private String descripcion;
public int getCodigo() {
return codigo;
}
public void setCodigo(int codigo) {
this.codigo = codigo;
}
public String getDescripcion() {
return descripcion;
}
public void setDescripcion(String descripcion) {
this.descripcion = descripcion;
}
}
which is populated with values in a dispatcher. In the dispatcher I've
private Articulo articulo;
.......
public Articulo getArticulo() {
return articulo;
}
public void setArticulo(Articulo articulo) {
this.articulo = articulo;
}
There is also a JSP with
<s:property value="articulo"/>
which read ok the articulo. Also works articulo
<s:property value="articulo.codigo"/>
But now I want from that jsp forward the entire object articulo to another action.
I can do
<s:hidden name="articulo.codigo" value="%{articulo.codigo}"/>
<s:hidden name="articulo.descripcion" value="%{articulo.descripcion}"/>
and that works fine, but is there anyway to do something like
<s:hidden name="articulo" value="%{articulo}"/>
So, is there anyway to get the object from JSP without setting all the properties of it?
there are 2 points:
Problem: you can't transfer object using <s:hidden />, all the parameter, what are transfered with HTTP should be string. Since you cannot convert this object to String, you can't transfer it using HTTP either.
Solution: You can put your object into session, so that you can access it anytime you want. here is an EXAMPLE
Yes, you can transfer object in two ways either by parameter or store it in session and access it whenever you need it.
<jsp:forward page="URL" >
<jsp:param name="ParamName1" value="YourObject" />
</jsp:forward>
Visit here for more detail.
http://www.gulland.com/courses/jsp/actions/forward
Keeping the object information in sessions is usually the preferred method.
But an alternative option is to create your own Type Converter.
Create a type converter by extending StrutsTypeConverter. The
Converter's role is to convert a String to an Object and an Object to
a String.
By doing so, you could so something like <s:hidden name="articulo" value="%{articulo}"/>
Keep in mind this method is insecure as the object values will be printed out as String in the hidden tag and can be seen through the browser.
But the advantage is that this method works across different sessions if you have a need for such a thing.
How the data transfer from the action class to Jsp page in struts2.
Is any kind of stack is build inside the action class before its transfer its control to the jsp page , or there is something other mechanism is used for that.
Anshul,
You are some what correct in your implementation.For Struts2 we can see it in following manners
ValueStack
OGNL
Value stack is a virtual stack in Struts2 framework and a central place where all the data related to request processing will be placed by the Framework.In Struts2 Actions are also treated as a data carrier, so what exactly is happening is when the action done its work it is being placed on the top of value stack.
Lets we have something like this in Action
public class MyAction extends ActionSupport{
private String firstname;
private String lastname;
public void setFirstName(firstname){
this.firstname=firstname
}
public void setLastName(lastname){
this.lastname=lastname
}
public String getFirstName(){
return firstname;
}
public String geLastName(){
return lastname;
}
public String execute() throws Exception{
//action logic filling first name and last name from database etc.
return SUCCESS;
}
}
now when action will return after the logic framework will place action instance on the top of value stack and firstname and lastname will be on the top of it.
so now when we try to access these values in jsp something like
<s:textfield name="firstname" value= "%{firstname}"/>
here (%{firstname}) OGNL will come in to place and it will try to see if there is a property in the value stack with name firstname,since action is on the top of value stack and it has property name firstname in it so OGNL will find it.
i hope this will help you