I am working on a struts2 project. I have created url with in my project and have passed parameters using tags. My question is how do i read the parameter in the actions? also if do the same would i be able to see the parameters as query string. i ask because i am not able to and i saw it in one of the tutorials.
Typically, you will interact with parameters in your actions by using fields on your actions, exposed by setters. Assume the following URL maps to my example Struts2 action:
URL
http://localhost/myAction?firstName=SonOfTheEARTh
Action Code
public class MyAction extends ActionSupport {
private String firstName;
public String execute() throws Exception {
// do something here
return SUCCESS;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(final String firstName) {
this.firstName = firstName;
}
}
JSP
Using Struts tags: <s:property value="firstName"/>
Using JSP EL/JSTL: ${action.firstName}
EDITED answer: It's based on naming conventions of your parameter. Take a look at this link and follow how they set "oldName" parameter.
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.
Imagine the following scenario:
I send a request to a service (which uses Play framework) with the following parameters (parameter's name should be underscored by convention):
first_name=James&second_name=Parker
Moreover I have a model class in my codebase which looks like this.
public class User {
#Constraints.Required
private String firstName;
#Constraints.Required
private String secondName;
public String getFirstName() {
return firstName;
}
public String getSecondName() {
return secondName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setSecondName(String secondName) {
this.secondName = secondName;
}
}
All I want to do is to map parameter's names with the corresponding
field names. The following statement using Play Framework fails because
User object cannot be initialized with the given parameters of request.
Form<User> form = Form.form(User.class).bindFromRequest();
Read this first: https://www.playframework.com/documentation/2.1.1/JavaRouting
And then:
GET /myMethod/:firstName/:seccondName controllers.MyController.myMethod(firstName: String, seccondName: String)
and simple Method:
public myMethod(String firstName, String lastName) {
User u = new User();
u.setFirstName(firstName);
u.setSeccondName(seccondName);
}
Obviously if you use play framework 2.
You have underscores in the request parameter names, yet your class has the members in camelCase (e.g. first_name vs fistName [Missing a r here]).
Secondly it also seems like these class members are declared private AND you have no setter methods only getters (i.e. setFirstName).
In order to do the binding your class is instantiated and the values are set and with no way to do so it will fail.
Once you've fixed the above, you should be able to bind and then call form.hasErrors() to check if validation has failed.
Hope that helps.
Update:
To handle the mismatch between the request parameter names and the class member names you would probably have to manually set things up.
In your controller method you would do something like this:
Map<String, String[]> reqBody = request().body().asFormUrlEncoded()
Map<String, String[]> newReqBody = new HashMap<>();
for(Map.Entry<String, String[]> entry: body.entrySet()) {
newBody.put(underscoreToCamelCase(entry.key()), entry.value());
}
Form<User> form = Form.form(User.class).bindFromRequest(newReqBody);
Note that I'm using the overloaded version of bindFromRequest as seen here
You should then implement the underscoreToCamelCase method in a generic enough way to handle all your conventions (Perhaps you might have a situation where there are more than one underscores).
Is there a way to set resource relations through annotations? I made a similar question a some time ago but i've not been clear enough. I want to have something like this:
public class UserResource {
private String username;
#Relation(value = "{servicebaseUrl}/classes/${value}", rel = "class")
private String classId;
// Getters and setters
}
And then add a message converter which would add links only if client sends Accept = application/hal+json, avoiding the fact of doing two different controller endpoints for application/hal+json and application/json. Does Spring offers something like that? I found that it actually offers this #Relation annotation(or similar one) but it seems that it is not for the same purposes.
No this is not possible - you would have to implement a ResourceAssembler to add links to your resources.
Usually your resources extend ResourceSupport.
class PersonResource extends ResourceSupport {
String firstname;
String lastname;
}
Then your create ResourceAssembler to control the creation of that resource:
class PersonResourceAssembler extends ResourceAssemblerSupport<Person, PersonResource> {
public PersonResourceAssembler() {
super(PersonController.class, PersonResource.class);
}
#Override
public PersonResource toResource(Person person) {
PersonResource resource = createResource(person);
// … do further mapping and add links
resource.add(new Link("http://myhost/people"));
return resource;
}
}
See the spring hateoas documentation for details
I want to code a REST API that is multileveled like:
/country
/country/state/
/country/state/{Virginia}
/country/state/Virginia/city
/country/state/Virginia/city/Richmond
I have a single java class that is a Country resource with #Path("country")
How do I create a StateResource.java and CityResource.java so that my Countryresource can use the StateResource in the way I am planning to use it? Any useful links on how to construct this kind of thing in Java?
The CountryResource class needs to have a method annotated with the #Path to the sub-resource CityResource. By default, you are responsible for creating the instance of CityResource e.g.
#Path("country/state/{stateName}")
class CountryResouce {
#PathParam("stateName")
private String stateName;
#Path("city/{cityName}")
public CityResource city(#PathParam("cityName") String cityName) {
State state = getStateByName(stateName);
City city = state.getCityByName(cityName);
return new CityResource(city);
}
}
class CityResource {
private City city;
public CityResource(City city) {
this.city = city;
}
#GET
public Response get() {
// Replace with whatever you would normally do to represent this resource
// using the City object as needed
return Response.ok().build();
}
}
CityResource provides the methods that handle the HTTP verbs (GET in this case).
You should look at the Jersey documentation regarding sub-resource locators for more info.
Also note that Jersey provides a ResourceContext to get it to instantiate the sub-resource. If you're going to use #PathParam or #QueryParam in the sub-resource I believe you need to use this as the runtime doesn't touch sub-resources when created yourself via new.
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