Pregunta

I'm developing a Java Library project with Struts 1 (I know it is old, but this is a school project).

I created a DispatchAction to handle the Book requests for different methods (add, edit, delete) with op parameter.

The add method works fine because it has url like /book.do?op=add , but edit has a conceptual problem with a dynamic url like book.do?op=edit&id=1 :

if the validation find some errors, how can the action know where redirect? The input attribute is static, but the page that sends the request has a dynamic url.

I have this in my struts-config.xml:

     <!-- Base Book Action -->
    <action path="/book" type="com.github.jcpp.jathenaeum.actions.BookAction" parameter="op">
        <forward name="add" path="page.addBook"/>
        <forward name="edit" path="page.editBook"/>
        <forward name="delete" path="page.deleteBook"/>
        <forward name="viewAll" path="page.viewAllBooks"/>
        <forward name="noAuthors" path="page.noAuthors" />
    </action>

    <!-- Action Book -->
    <action
        path="/doBook"
        type="com.github.jcpp.jathenaeum.actions.BookActionDo"
        name="bookForm"
        scope="request"
        validate="true"
        parameter="op">
        <forward name="add" path="page.confirmBookInsert"/>
        <forward name="edit" path="page.confirmBookInsert"/>
        <forward name="success" path="page.confirmBookInsert"/>
        <forward name="failed" path="page.failedBookInsert"/>
    </action>

What I want to know is: this is the best way to do this kind of thing? Or there are simpler ways to do it?

Can I set the value of the input attribute in a dynamic way?

If you want you can check the entire project code on GitHub: https://github.com/JCPP/JAthenaeum

UPDATE 1

My problem is to redirect to a dynamic url like this: book.do?op=edit&id=1, after validation. The book that you can change can has a different id (29, 50, 49). The input attribute in this case is narrow.

Thanks

¿Fue útil?

Solución 2

There are some things to set. First things first.

Struts-config

In BookAction the application will show the form, while in BookActionDo it will update the book in the database.

<!-- Book -->
<action path="/book" type="com.github.jcpp.jathenaeum.actions.BookAction" parameter="op">
  <forward name="edit" path="page.book.edit"/>
</action>

<!-- Book Operations -->
<action
  path="/doBook"
  type="com.github.jcpp.jathenaeum.actions.BookActionDo"
  name="bookForm"
  scope="request"
  validate="false"
  parameter="op">

  <!-- Edit-->
  <forward name="editErrors" path="/book.do?op=edit" redirect="true"/>
  <forward name="editSuccess" path="page.book.edit.confirm" />
  <forward name="editFailed" path="page.book.edit.failed" />

Here it tells to struts to not validate the form with validate="false".

Actions

public class BookActionDo extends DispatchAction {

 public ActionForward edit(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response)
                throws Exception {
    String actionTarget = null;

    HttpSession session = request.getSession();

    Book book = new Book();
    BookForm uf = (BookForm) form;

    //Check the id
    if(!uf.validateId(mapping, request).isEmpty()){
        actionTarget = "invalidId";

        ActionRedirect redirect = new ActionRedirect(mapping.findForward(actionTarget));
        return redirect;
    }

    ActionErrors actionErrors = uf.validate(mapping, request);
    int id = Integer.parseInt(request.getParameter("id"));

    //If there are some errors, redirect to the form page
    if(!actionErrors.isEmpty()){
        actionTarget = "editErrors";

        session.setAttribute("errors", actionErrors);
        session.setAttribute("form", uf);

        ActionRedirect redirect = new ActionRedirect(mapping.findForward(actionTarget));
        redirect.addParameter("id", Integer.toString(id));
        return redirect;
    }

    if(form != null){
        book = new Book(uf);
        book.setId(id);

        try{
            int bookId = (int) BookDAO.update(book);

        }catch(Exception e){
            actionTarget = "editFailed";
        }
    }

    return mapping.findForward(actionTarget);
 }
}

Here it checks if validate of the form returns some ActionErrors. If yes it create an ActionRedirect with the id parameter, otherwise it tries to update the book.

So when it creates the url, ActionRedirect will redirect to: /book.do?op=edit&id=<book_id>.

Otros consejos

I don't think you can change the value of input attribute dynamically.

When your form is submitted and fails validation, it gets redirected to the page defined in the "input" attribute.

I don't see the need to change the "input" attribute dynamically. When the validation fails, you can redirect it back to the same page, where the user inputs data, with error message showing the invalid fields.

You can see this kind of behavior in any "Registration/Login" page of a website, when you enter invalid data.

EDIT

This is a work around. Set validate="false" in your mapping file. And call the validation method from your action class. You can also change the return type of the validate method to fit your need(for eg to a string). So in your action class depending on the value returned by the validate method you can create different urls and forward it there:

public class MyAction extends DispatchAction{

public ActionForward add(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response,
            ActionMessages messages) throws Exception

       MyForm myForm = (MyForm) form;
       String url="";
       String result = form.validate();

       if(result.equals("something")){
              url="book.do?op=add&id=" + book.getId();
        }else if(result.equals("somethingElse"){
              url="book.do?op=edit&id=" + book.getId();
       }

       RequestDispatcher rd = request.getSession().getServletContext().getRequestDispatcher(url);
       rd.forward(request, response);
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top