ART#113 - How to use/create formhandlers in ATG?



Forms are the essence of any web application.. be it J2EE or Spring or Hibernate, today every site has form.. ATG is no different.
Using forms in ATG is a piece of cake.. as you'll soon see..!

What are Forms?
Remember that page where you write your details so sign-up for an email account? That is a form. A form is a web-version of a normal paper forms you see in the real world. It has some places where you fill up the relevant details, and submit the form to the web server.
In ATG, you create (or use) a FormHandler (just like a simple component), and integrate your form with a JSP so that relevant action takes place when you submit the form.

How does a formhandler function in ATG?
A Formhandler is just like any other component. They can exist out-of-the box, and can be used as-is OR they can be extended like any other component OR they can be created right from scratch.
To start with, formhandlers mostly are of "request" scope as we dont want our form-data to be manipulated multiple times. If our formhandler's scope is session or global, our submitted form data can be modified within a session or globally by any user worldwide..!!
This, however does not mean something is keeping you from setting the scope of a formhandler to session/global. I'm just saying that do it at your own risk.. (NEVER EVER SHOULD YOUR FORMHANDLER BE GLOBAL!!). There could actually be some scenarios where you'd want to keep your formhandler as session scoped.

How to create a formhandler from scratch?
Always remember, a formhandler is a normal component and can be created just like any other component is created.
You create a class, create a configuration file, keep your component scoped as "request" (mostly) and you're good to go..! Or NO?
When you create a component from scratch, you create a class and extend "GenericService" to provide your component with Nucleus features.
Similarly, for a FormHandler, you can extend "EmptyFormHandler" class or "GenericFormHandler" class. 

Now let us ask ourselves a question, what would a formhandler require? Or, to rephrase is, what does a form CONTAIN and what does it DO?

1. Firstly, there should be a FORM to have fields. So, we create a JSP and create a form. Inside a form, we write the <dsp:input> tags for getting the input from user against the form fields. See below screenshot for details.



Here, we have created a form with two text fields named, fName and lName with a submit button.
We have not provided a form-action yet. We will be discussing actions in further steps.
2. Now that you have a form with some fields, we need to pass it to some JAVA code to process it. The "JAVA code" resides inside our formhandler.
In our formhandler (or to say our component which extends GenericFormHandler and has request scope), we should have JAVA fields corresponding to the fields in out JSP form. These JAVA fields can have same name or something else.. it does not matter. See below screenshot.




Our class extends GenericFormHandler class, has two fields firstName and lastName which correspond to form fields fName and lName in the JSP.
Next, we have setters and getters for these two fields.

3. Now we have a form, we have a formhandler with corresponding fields. We need to map the JSP form fields to our formhandler's "corresponding" properties. We do this in our JSP. See below screenshot to see the highlighted changes in the JSP.



We import the component (configuration file) which points to the class we crated in Step#2. Next, we provide a "bean=" attribute to the <dsp:input> tags to map the text fields to formhandler fields.

4. Our form is created, we have fields mapped to formhandler. Now we need to submit the form and do some real action..!!
For this, we follow the below steps:-


a. Create a method named public boolean handleXXX(DynamoHttpServletRequest pRequest, DynamoHttpServletResponse pResponse) in your formHandler. Here, "XXX" can be replaced by your logical name. (Below screenshot)



b. This method can access the fields in the formhandler which are mapped to JSP Form Fields.

c. Write custom code in handleXXX() method to perform specific action (like storing these fields in repository or session or anywhere)

d. Next you call this custom method from your JSP's submit action. See below screenshot for this. 



Here, you are telling the submit button to call your handler method written in your java file (your formhandler class). HelloWorldFormHandler.myForm represents your handleMyForm method in your formhandler.
Whatever you name your handler method (handleMyForm), just remove the "handle" keyword (it becomes MyForm), convert the next character into lowercase (it becomes myForm), and use it in your formhandler (marked in red box), and your are good to go..!!!!

Now that we have got our basic flow sorted, you must be wondering, "NO url has been provided in the form for "action" attribute in form tag, where does it redirect to?? Should it redirect or not..? or whatever..! Just read on..!

How to redirect a form in case of failure or success?

The class GenericFormHandler, which you extend, has a method called checkFormRedirect() which is of type boolean.
You can use this method to control redirects. The API call of this method looks somewhat like:-
public boolean checkFormRedirect(pSuccessURL, pFailureURL, pRequest, pResponse);

Now, this method redirects to pSuccessURL if no form errors are found in the form. Otherwise, it redirects to pFailureURL.

Therefore, you can use it in the following way (see below screenshot):-



Now, in the same class (HelloWorldFormHandler.java), we have added two new variables viz. helloWorldSuccessURL and helloWorldFailureURL. We have setters and getters for these methods. Also, we have called the checkFormRedirect() method in our handler method to redirect to appropriate pages.

We can set these success/failure URLs in configuration file for this component (just like we set any other component property in the configuration file), 
OR 
we could pass it form the JSP (just like we mapped fName and lName to component properties, except, fName and lName were input fields of type "text", these URLs will be of type "hidden"). See below screenshot for the JSP snippet.




We're mostly done with the basics of formhandlers but wait..! what if.. you add "action" attribute to your <dsp:form> tag and provide an action URL? How would ATG behave?
Let us say you provide "action=<some URL>" in your <dsp:form> tag. Now there could be two scenarios:-

1. You have used checkFormRedirect() method in your handler method.
In this case, the action attribute in the <dsp:form> tag will be ignored.

2. You have NOT used checkFormRedirect() method in your handler method.
In this case, your form will redirect to URL mentioned in the action attribute of the <dsp:form> tag irrespective of failure or success.


Out of The Box Formhandlers!

There are tonnes of OOTB formhandlers viz.
ProfileFormHandler - Handling login/logout/registration etc.
CartModifierFormHandler - For Handling add/remove/update items to/in the cart.
RepositoryFormHandler - For saving data to repository.
ExpressCheckoutFormHandler - For checkout process and placing an order.
etc. etc.

Please note that for every handleXXX method in OOTB formhandlers, there is a preXXX and postXXX method called before and after the actual handler code.
You can chose to override these pre and post methods if necessary rather than overriding the actual handler method itself.

For example, in ProfileFormHandler, there is a method handleLogin.
For this method there are two methods preLoginUser and postLoginUser.
Therefore, you can put all your email and password validation in preLoginUser method and some of the post login actions you can override postLoginUser. In these cases you dont need to override the whole handler method itself.
Check the original API for individual formhandler to check these handler and pre/post methods.

Next, we will understand servlet pipelines in ATG.

Back



Next






33 comments:

  1. Excellent, thank you very much. Though there is lot of documentation, it was hard to start. You helped me to kick off. Appreciating your work...!! Thanks again...

    ReplyDelete
  2. Hi Sandeep,

    Thanks a lot for the appreciation. Glad the article helped :)

    ReplyDelete
  3. Thank you Monis! Your tutorial is a boon! Really the documentation are very difficult to start with and your tutorials are like life saver.
    Best wishes for your bright future!

    ReplyDelete
  4. Thanks a lot for the appreciation Reena :)

    ReplyDelete
  5. Thanks Monis.. Your blog is a saviour. Hope to see more ATG related topics.

    ReplyDelete
  6. Hi Yousuf,

    Thanks a lot for this awesome tutorial which made us easy to understand ATG topics easily,great job.
    I request you to add ATG search topics.

    Thanks,
    Reshma

    ReplyDelete
    Replies
    1. That is on the list.. We will add that soon.

      Delete
  7. Hey Yusuf...

    Love you dear ...you made my ATG learning easy....

    ReplyDelete
  8. thanks for the info ... you made it simple for me ..thank you

    ReplyDelete
  9. Hi Yusuf,

    Im a beginner in ATG. I have query on submitting a form using js. Suppose im using a button instead of submit and onclick of the button im submitting the form in a js,i have an hidden field which calls a method in form handler.i need to know how the submit call exactly calls this hidden fields method.Will there be any mapping in ATG.

    ReplyDelete
    Replies
    1. 1. Create a submit button, make it non-visible by adding style="display:none" in the input tag.
      2. Next, create your button.
      3. On click of the button bind the "submit" operation.
      [e.g. on click of "button", your form.submit() action should be called]

      This is purely from javascript perspective, no changes from ATG side is required.
      Let me know if it solves your problem, otherwise you can reach out to me again.

      Delete
  10. Thank you Yusuf. Im very much interested to know how the submit action gets the control to the form handler's exact method.

    ReplyDelete
    Replies
    1. It pretty much happens OOTB.
      When you create a handleXXX method in a formhandler (say ABCFormHandler), and set a , then ATG prepends "handle" to the "XXX" and binds it directly to the ABCFormHandler's handleXXX method.

      Delete
  11. Thank you. So the preXXX and postXXX are called before and after handleXXX accordingly.

    ReplyDelete
    Replies
    1. No, preXXX and postXXX are not called automatically.
      They have to be created manually and called inside the handleXXX method.

      Some OOTB formhandlers provide preXXX and postXXX methods, but there is no binding for that. They call these pre and post methods directly in handleXXX method.

      therefore, handleXXX would contain
      {
      preXXX();
      //some statements for actual operations
      postXXX();
      }

      Delete
  12. G8 blog..!!!
    ATG made easy...

    # Can you also cover Scheduler in your blog ?

    ReplyDelete
  13. Monis,
    how can i show a Custom success or error message at the Success JSP after the formhandler handle method is called.

    say in above JSP after form submit, we want to show success-message (Thank you for providing your fName and Last name)

    or in case 2, (your fName and Last name is already with us)

    ReplyDelete
    Replies
    1. In the handler method you can set a request parameter.
      request.setParameter("your_parameter_name", "your success message");

      When your JSP is reloaded using a successURL, you can print this parameter using below tag
      < dsp:valueof param="${your_parameter_name}" / >

      If it is empty, it will not print anything, if it has your success message, it will print it.

      Delete
  14. Hi Monis, one question regarding successURL and failureURL. You mentioned that one way is to provide it in JSP. I saw your example above. But I didn't see the actual success url and failure url in jsp. Could you please help understand where it is set?

    ReplyDelete
    Replies
    1. If your HelloWorldFormHandler has "helloWorldSuccessURL" and "helloWorldFailureURL"; then you can see the code in last image of this article. The success and failure URLs are set in the HelloWorldFormHandler.

      Alternatively, you can also hardcode this:-
      < dsp:input name="successURL" value="https://www.google.com" / >

      Delete
  15. How i can redirect to multiple success page depending on different condition?

    ReplyDelete
    Replies
    1. In your formhandler, based on your conditions, set the value of successURL and failureURL, and finally call checkFormRedirect.

      Example:

      if(condition1) {
      successURL = "something";
      failureURL = "something...";
      } else {
      successURL = "condition2Something";
      failureURL = "condition2SomethingFailure";
      }
      checkFormRedirect(successURL, failureURL, pRequest, pResponse);

      Delete
  16. Please add an article on commerce pipeline

    ReplyDelete
  17. Just add one sample atg project also in your blog it will help us alot...... Thanks for the great work you are doing really helpful this blog.

    ReplyDelete
    Replies
    1. Creating a sample project and setting up CRS are on the list and will be uploaded within a couple of weeks.

      Delete
  18. Hi Monis,

    In your previous article you have mentioned that the dsp:importbean tag must be used before dsp:page and after taglib declaration. However, in the above screenshot, you have included the dsp:importbean tag after dsp:page. Does that work or is it a mistake?

    ReplyDelete
    Replies
    1. Hi Anand,
      Thanks for pointing it out. It has now been corrected.
      dsp:importbean tags should come WITHIN dsp:page tags.

      Delete
  19. Hi monis,

    I have a small doubt. Let us say i have extended ProfileFormHandler and created my own formhandler "MyRegisterationFormahandler" and my custom formhandler has all the getters and setters for user details. My question is now i want to store the user details which are in my fields in user item-descriptor so for this i have to create a item for that item-descriptor and set each property or can i use super.handlecreate() to store it in OOTB tables.

    ReplyDelete
    Replies
    1. super.handleCreate() will store in the repository (even in auxiliary tables). You just have to populate a map containing property-name (custom/OOTB) and its value.
      For example, you have firstName as OOTB property and alternatePhoneNumber as a custom property, you will have to create a Map (or DIctionary) something like:-
      firstName:
      ... other mandatory properties...
      alternatePhoneNumber:

      You pass this map and the ProfileFormHandler will automatically store the values in their corresponding tables.

      Delete

Subscribe

Get All The Latest Updates Delivered Straight Into Your Inbox For Free!

Flickr