Should I Retrieve Database Record in Struts2 View Layer

Should I retrieve database record in Struts2 view layer?

Using Struts2 you won't need to use Scriptlets (<% stuff %>) anymore. They're old, bad, they're business logic injected in view pages, do not use them. You do not need JSTL neither, just using Struts2 tags you can achieve any result.

For a better decoupling and separation of code and concepts, you should have:

  1. DAO Layer: it does just the plain queries;
  2. BUSINESS Layer: it exposes the DAO Layer results through Service(s), aggregating multiple DAOs calls and performing several business operations when needed;
  3. PRESENTATION Layer: The Actions, that in Struts2 acts as the Model; here you call the Service from the Business Layer, to retrieve the objects needed by the JSP;
  4. JSP (VIEW Layer): the JSP contains the plain HTML, and accesses the data needed through the Accessors (Getters) of the Action, and eventually any other needed element from the Value Stack (#session, #request, etc).

    In your example, all of this

<% 
Session session2 = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction tx = session2.beginTransaction();
Query q = session2.createQuery("from Subject");
List subjectList = q.list();
List levelList = session2.createQuery("from Level").list();
%>

should be in DAO/Business Layers, exposed by two function like getSubjectList(); and getLevelList();. Then in your Action you should have something like:

public class YourAction {

private List<Object> levelList; // private
private List<Object> subjectList; // private

public String execute() throws Exception {
// Call the service, load data
levelList = getMyService().getLevelList();
subjectList = getMyService().getSubjectList();

// Forwarding to the JSP
return SUCCESS;
}

public List<Object> getLevelList() {
return levelList;
}
public List<Object> getSubjectList() {
return subjectList;
}

}

and in your JSP, instead of:

<select name="subject_id">
<%
for (Object subjectObject : subjectList) {
subject subject = (Subject) subjectObject;
%>
<option value="<%=subject.getId()%>"><%=subject.getName()%></option>
<%
} //end for
%>
</select>

you access the list like (ugly mixed HTML/Struts2 way):

<select name="subject_id">
<s:iterator value="subjectList">
<option value="<s:property value="id"/>">
<s:property value="name"/>
</option>
</s:iterator>
</select>

or, in the case of a Select, with the proper Struts2 UI Select Tag:

<s:select name = "subject_id" 
list = "subjectList"
listKey = "id"
listValue = "name" />

If separating all the layers is too difficult at the beginning, flatten the first three levels in the Actions, just to understand how to separata Java (Action) and Struts2 UI Tags (JSP).
When understood, you can move the DAO logic to the business layer, preferably into an EJB. When achieved that, split again with more granularity...

The Action will be something LIKE this:

public class YourAction {

private List<Object> levelList; // private
private List<Object> subjectList; // private

public String execute() throws Exception {
Session session2 = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction tx = session2.beginTransaction();
Query q = session2.createQuery("from Subject");
subjectList = q.list();
levelList = session2.createQuery("from Level").list();

// Forwarding to the JSP
return SUCCESS;
}

public List<Object> getLevelList() {
return levelList;
}
public List<Object> getSubjectList() {
return subjectList;
}
}

About your question on multiple loading of the lists, you can use a cache (better if with a timer) if the list is fixed (it changes one a month for example), or loading it every time, there aren't problems in doing that.
Please note that if validation fails, the ValidationInterceptor will forward the request to the JSP mapped in the INPUT type result, without reaching the execute() method, so you should implement Preparable interface from Action and put the loading stuff into prepare() method, execute every time by the PrepareInterceptor

public class YourAction implements Preparable {

private List<Object> levelList; // private
private List<Object> subjectList; // private

public void prepare() throws Exception {
// Call the service, load data,
// every time even if validation fails
levelList = getMyService().getLevelList();
subjectList = getMyService().getSubjectList();
}

public String execute() throws Exception {

// Forwarding to the JSP
return SUCCESS;
}

public List<Object> getLevelList() {
return levelList;
}
public List<Object> getSubjectList() {
return subjectList;
}
}

Proceed by steps, the framework is easy and powerful, the web has plenty of examples and StackOverflow provides some great support...

Paging in struts 2

The problem can be solved by adding following attributes to the displaytag table.
partialList="true" size="resultSize". Here resultSize is the variable where you assign the total row count of the result inside the action class. More information can be found here

display:table using Struts action results

Solved by using the action in a jquery load on the div tag... as Dave said, too many pieces –

Dynamic url using s:iterator in struts2

There are two problems:

  1. If you are generating an url for each element of a Collection, then you need to put the url generation inside the iteration of that Collection, otherwise you will have always the same url:

    <ol>
    <s:iterator value="puntate">
    <s:url action="episodi" var="episodio">
    <s:param name="id">something here</s:param>
    </s:url>

    <li><a href="<s:property value='#episodio'/>"><s:property/></a></li>
    </s:iterator>
    </ol>
  2. You have not used OOP, that would suggest to create a bean named Movie (or Film), with a List<Episode>, and Episode should be another bean with for example Long id, Integer season, Integer number, and String description.

    Since you've used two different lists, one for the episode description and another one for the episode id, and assuming they're aligned (it is not guaranteed, so I strongly suggest you to refactor your code the OOP way), you can access the IDs by their index basing on the episode description index, during the iteration:

    <ol>
    <s:iterator value="puntate" status="ctr">
    <s:url action="episodi" var="episodio">
    <s:param name="id">
    <s:property value="idPuntate[%{#ctr.index}]"/>
    </s:param>
    </s:url>

    <li><a href="<s:property value='#episodio'/>"><s:property/></a></li>
    </s:iterator>
    </ol>

P.S: Film should be a bean declared in your action, not the action itself... otherwise it is not portable... what if you need the Film class in other actions ?

To check whether that user already exists or not in struts2

Your problem is that the validate() method, run by the Validation Interceptor,
is executed before reaching the action, and hence before the execute() method.

This means that temp_user is always null when read in the validate() method.

You need to learn how Struts2 works, especially when and how the Interceptors are called between the JSP and the Action.

Solution: load the temp_user variable inside the validate() method.

Also read Should I retrieve database record in Struts2 view layer? for a discussion on how to make your code cleaner and more decoupled, because all that JDBC stuff in the action is really ugly.

how to prevent struts2 auto data convention from throwing exception

First, you have to validate the data that the user entered in your form. This can be done in many ways, with Annotations (section Validation Annotations), with XML or with a simple validate() method in your action. You can search on the Internet lots of examples of how to validate data with Struts2 if the official documentation isn't enough.

Then I want to add something related with your jsp. Struts2 has built-in tags that render lots of things and help you to communicate the action with jsps. If we are talking about forms, we have for example <s:form> that can help you, for example, not to hardcode the url of the action in an HTML form or <s:textfield> that can be useful for render validation errors.

If the problem is that you want to use the Twitter Bootstrap notation for build your page, there is a plugin that render the HTML ready to use that CSS Framework.

EDIT

WARNING: Error setting expression 'courseBean.fee' 
with value '[Ljava.lang.String;@1b40489'

The problem with your aproach is that you are trying to assign a String [] to a field that probably isn't a String [] (maybe it's a Date). You have to take the String and parse it to convert it to a Date object. Also, if you don't know how <s:textfield> and <s:form> work in Struts2, you should take a look at this tutorial. It could be helpful for you.

Populate drop down list with jsp, struts2 & postgresql

There are a lot of things gone wrong.

The most important one is that you must always call an action that then renders a JSP, you should never call directly a JSP. Instead, you are calling

window.location = '/ReportBuilder/myreports.jsp';

that will open a JSP without passing through an action. And hence, without having any action data to pass to it and populate your select.

Actually, the action data is available only in the xhttp.onreadystatechange = function() { function, then you create another request and lost it.

You need to do something like window.location = "/some.action"; where some.action will load the data needed by the select and forward to your JSP, and then it will work, but since you've already called the action needed to populate the select before, the whole thing need to be rethinked.


That is the error, but after thant, here are some suggestions:

  1. Using an <s:iterator> to populate a select ? It's better to use the <s:select /> tag. It's all described in this answer that I suggest you to read, along with the question, to also understand why and how you could shape better your application's layers, instead of putting business logic in the actions, that in fact are presentational controller.

  2. Using vanilla Javascript instead of jQuery is a bad idea for beginners who are not forced by company rules to explicitly avoid jQuery. If you can use it, just use it.

  3. Take a look at the Struts2 jQuery plugin, that will allow you to use jQuery without even knowing it, by just using Struts2 tags.

  4. Use HTML5 DTD. It's backward compatible and it's way better than 4.01 that will force strange quirks on different browsers.

  5. CSSs are better than in-page <style> blocks that are better than inline styles.

  6. Changing a page to populate a select ? Isn't it better to populate a select on the same page ?

save multiple attachments in java

You can upload multiple files like described here, then you simply need to loop them and insert them in the database one at time.

You just need to decide if using a business layer or doing the insert job directly from the Action (not the best practice...), and if putting all the files in a single transaction or each one in its own.

Remember that HTML5 multiple attribute should be multiple="multiple", not just multiple (although the majority of the browsers handles it right even when "quirk").



Related Topics



Leave a reply



Submit