Win a copy of Java Concurrency Live Lessons this week in the Threads forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Calling forms from within a servlet and returning that information to a database  RSS feed

 
Devin Crane
Ranch Hand
Posts: 32
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I know what I want to do, but I'm not sure the best or right way to do it, and I'm not finding quite what I'm wanting on Google.

I have a java servlet that accesses a sql database and displays the information in the browser.
I want to add a button that would bring up another browser page/tab containing a form allowing me to fill in fields that would be added to my sql database when a Submit button is pressed.
The original servlet would then update, either automatically (preferably) or by hitting the browser's refresh button, and show the new entry.

Do I need a form in the original servlet for the button to call the other page/form with?
Or should the new page I want to generate be a separate servlet, for which my original web.xml would contain another entry or just another form in my original servlet?

Hopefully that makes sense.

Any help is greatly appreciated,
Devin
 
William Brogden
Author and all-around good cowpoke
Rancher
Posts: 13078
6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The original servlet would then update, either automatically (preferably) or by hitting the browser's refresh button, and show the new entry


That comment indicates to me that you have not yet fully absorbed the principles servlets use.

Once servlet A has gotten a request and created a response web page, it no longer knows a thing about this particular client. It is not sitting there waiting to send more data.

It will take a separate request to servlet A to get a new page with modified data.

Time to break out the whiteboard or pencil and paper and diagram the data flow.

Bill
 
Devin Crane
Ranch Hand
Posts: 32
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for that bit of information; I wasn't sure. I just barely jumped into servlets 2 days ago at my boss's request.
You addressed one part of my question, but I don't feel like I fully understand just what needs to happen. I'm trying.

Am I talking about calling another servlet from the 1st servlet, both of which might contain a form?

Maybe point me in the right direction or something. I don't think I understand enough to diagram the data flow yet.

Thanks,
Devin
 
Bear Bibeault
Author and ninkuma
Marshal
Posts: 65833
134
IntelliJ IDE Java jQuery Mac Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Key concept: Separation of Concerns.

You are making a classic mistake of trying to make each component do too much.

Here's a typical flow:
  • A servlet (page controller) receives a request to display the page with the form.
  • The controller gathers any data that's need, if any (e.g. inital values for the form fields), and puts those values into request scope as scoped variables (via setAttribute()).
  • The controller forwards to a JSP that defines the HTML to be sent to browser. Once the response is sent, the controller and JSP are done. Finis. No more.
  • The user interacts with the page and eventually hits the submit button.
  • The form is submitted to a different servlet (task controller) with responsibilities for updating the database (preferably by interacting with UI-agnostic model classes).
  • The task controller redirects to the page controller for whatever page is to be shown next. If it's the form again, it redirects to the page controller servlet for the form.

  • Notice how this differs from your original scenario. Important points are:
  • The page controller servlet's responsibility is preparing the request for the page to be displayed. It is not repsonsible for dealing with the aftermath of the form submission, and is not even responsible for generating any HTML.
  • The JSP is responsible for generating HTML. It is not reponsible for anything else, including getting its own initial values; that's the job of its controller.
  • A task controller servlet has responsibility for dealing with the form submission. No display responsbility; no prep responsibility.


  • The reasons for all this are outlined in this article. Give it a read.
     
    Bear Bibeault
    Author and ninkuma
    Marshal
    Posts: 65833
    134
    IntelliJ IDE Java jQuery Mac Mac OS X
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    P.S. If you're also new to JSP, also read this article.
     
    Devin Crane
    Ranch Hand
    Posts: 32
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Those articles helped a lot. Let me make sure I understand:

    Servlet A displays information from a database via jdbc and also has an Add button.
    If Servlet A's Add button is clicked, a JSP page is called, which creates a form that allows the user to add a new entry to the database via JDBC when a Submit button is selected. This is sent to the browser.
    Once submitted, Servlet B is called, with the information from the form, and Servlet B updates the database.
    Servlet B calls Servlet A again, thereby displaying the db information, including what was just added.

    But just to be clear, the JSP could do Servlet B's job; it's just bad design to. Are these ideas correct?

    Thanks,
    Devin
     
    Bear Bibeault
    Author and ninkuma
    Marshal
    Posts: 65833
    134
    IntelliJ IDE Java jQuery Mac Mac OS X
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Devin Crane wrote:Those articles helped a lot.

    Cool!

    Let me make sure I understand:

    Not quite, let's go through it:

    Servlet A displays information from a database via jdbc and also has an Add button.

    Servlets don't display anything. Every HTML page is created by a JSP, which is preceded by a page controller servlet. You should never emit HTML from a servlet. That's just a big old mess. The page controller servlet's job is to gather any data, or perform any other preparation, needed by its supported JSP.

    If Servlet A's Add button is clicked, a JSP page is called

    No. JSPs are never called directly, they are always invoked via their page controller. In fact, many developers place the JSPs under a folder in WEB-INF so that it is impossible to call the JSP directly.

    which creates a form that allows the user to add a new entry to the database via JDBC when a Submit button is selected. This is sent to the browser.

    The JSP has no idea what will happen when the submit button is clicked. The form simply specifies an action that is a task controller servlet whose job it is to gather the submitted data and perform the database operations (delgating to the model, ideally).

    Once submitted, Servlet B is called, with the information from the form, and Servlet B updates the database.

    Yes. (Again, though model classes.)

    Servlet B calls Servlet A again, thereby displaying the db information, including what was just added.

    The correct term is redirect, rather than "call".

    But just to be clear, the JSP could do Servlet B's job; it's just bad design to.

    In the same way that a sledgehammer can do the job of cutting a board. It's more than bad design, it's misusing the tool for the wrong purpose.
     
    Devin Crane
    Ranch Hand
    Posts: 32
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Ok. So after I create an ArrayList containing all the data from my database I want, I call



    Then to invoke the JSP, I use



    My servlet is in /WEB-INF/classes/test, and my JSP is in WEB-INF but doesn't seem to forwarding on. I'm trying to figure out what I'm missing.
     
    Bear Bibeault
    Author and ninkuma
    Marshal
    Posts: 65833
    134
    IntelliJ IDE Java jQuery Mac Mac OS X
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    You need to use the context-relative path to the JSP for the request dispatcher.

    Any time you feel like using ".." in a path in a web app, stop. It's going to fail. Never use "..".

    If the JSP is under WEB-INF, the path should start with "/WEB-INF".

    See the ServletsFaq on paths for more info.
     
    Devin Crane
    Ranch Hand
    Posts: 32
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I got my 1st JSP to work, and I have it displaying the list of items from the database and the Add button.


    Now I'm trying to have the Add button redirect to another servlet, addServlet.java, which will invoke another JSP, which will display a form to give info for another data entry in the db.
    Does this new servlet, addServlet.java, also go into the hello directory "webapps/hello/WEB-INF/classes/test/*.java" or go into a different directory?

    In the web.xml I currently have


    And I'm getting this error in the logs:
    Jul 08, 2013 2:51:48 PM org.apache.catalina.core.ApplicationContext log
    INFO: Marking servlet hello as unavailable
    Jul 08, 2013 2:51:48 PM org.apache.catalina.core.StandardWrapperValve invoke
    SEVERE: Allocate exception for servlet hello
    java.lang.ClassNotFoundException: test.addServlet
    at org.apache.catalina.loader.WebappClassLoader.loadClas


    Last time I had this error (it is a little different I think), I was using 2 versions of Java, but that's not the issue here.
    I think it's something with how I'm trying to redirect to the new servlet, but I'm not for sure.

    Thanks for the help!
    Devin
     
    Bear Bibeault
    Author and ninkuma
    Marshal
    Posts: 65833
    134
    IntelliJ IDE Java jQuery Mac Mac OS X
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Devin Crane wrote:

    .java? The Java files have nothing to do with run time.

    And onclick is for an event handler not a URL.

    I think you need to back up a bit and go over a tutorial on HTML and JavaScript.

    Are you using jQuery to help with the JavaScript? (If not, why not?)

    Does this new servlet, addServlet.java, also go into the hello directory "webapps/hello/WEB-INF/classes/test/*.java" or go into a different directory?

    The .java file doesn't go anywhere. Its class file needs to go in the WEB-INF/classes hierarchy. The .java files play no part in run time.
     
    Devin Crane
    Ranch Hand
    Posts: 32
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Sorry, I meant .class, not .java. Yeah, it was kinda dumb to use the onclick that way, I took it from the way I invoked the JSP form the servlet, using what you'd mentioned earlier:
    The form simply specifies an action that is a task controller servlet


    I figured the only way to do that was give it the path to the servlet, though it seems like it would be easier to just bypass the servlet and go straight to a new JSP.
    I obviously didn't quite interpret that correctly. I wasn't real sure, still aren't, same with my error. For some reason I'd assumed JSPs were limited to just HTML.

    I'm assuming the lack of comment on the web.xml means I did that correctly.

    Thanks,
    Devin
     
    Bear Bibeault
    Author and ninkuma
    Marshal
    Posts: 65833
    134
    IntelliJ IDE Java jQuery Mac Mac OS X
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Devin Crane wrote:Sorry, I meant .class, not .java.

    To address the servlet you would use the mapping set up in the deployment descriptor (web.xml), not the path to either of the class or java file.

    Yeah, it was kinda dumb to use the onclick that way, I took it from the way I invoked the JSP form the servlet, using what you'd mentioned earlier:

    Buttons and forms do not work the same way. To make a button submit, you'd set up an event handler that uses JavaScript to submit a request.

    though it seems like it would be easier to just bypass the servlet and go straight to a new JSP.

    Bad, bad idea. That way lies madness.

    Always go through the page controller for the page -- even if has nothing much to do.

    For some reason I'd assumed JSPs were limited to just HTML.

    JSPs aren't limited to anything except text. It doesn't matter what the template text is; JSP doesn't care. It could be HTML, it could be the Gettysburg Address.

    I'm assuming the lack of comment on the web.xml means I did that correctly.

    Ummm, didn't look yet.
     
    Bear Bibeault
    Author and ninkuma
    Marshal
    Posts: 65833
    134
    IntelliJ IDE Java jQuery Mac Mac OS X
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Devin Crane wrote:I'm assuming the lack of comment on the web.xml means I did that correctly.

    You have two servlets with the same name.
     
    Bear Bibeault
    Author and ninkuma
    Marshal
    Posts: 65833
    134
    IntelliJ IDE Java jQuery Mac Mac OS X
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    P.S. Why a button rather than form? I assume you have data to send to the servlet? And that it should be a POST rather than a GET?
     
    Devin Crane
    Ranch Hand
    Posts: 32
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Currently:
    helloServlet invokes display.jsp, which only displays the db info, with an add button.
    display.jsp's add button, when clicked is supposed to direct you to addServlet, but display.jsp has no info to pass on.
    addServlet invokes add.jsp, which creates the form to enter the info for a new db entry.
    add.jsp has a Submit button, which will call submitServlet, which will update the db.
    submitServlet will invoke display.jsp, which only displays the db info, with an add button.

    display.jsp works, except for the add button so it doesn't currently go anywhere.

    It appears a form, rather than a button, would make it easier so I think I will use it, but display.jsp has no info to pass on.
     
    Devin Crane
    Ranch Hand
    Posts: 32
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    If I change the 2nd servlet-name to 'add' and the servlet-pattern is '/addServlet', wouldn't I call addServlet from the form's action with "/add/addServlet"?
     
    Devin Crane
    Ranch Hand
    Posts: 32
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Here is my form HTML:



    Here is my web.xml again:
     
    Bear Bibeault
    Author and ninkuma
    Marshal
    Posts: 65833
    134
    IntelliJ IDE Java jQuery Mac Mac OS X
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Devin Crane wrote:display.jsp works, except for the add button so it doesn't currently go anywhere.
    It appears a form, rather than a button, would make it easier so I think I will use it, but display.jsp has no info to pass on.

    A button would be fine to use in this case (doing a GET with no request params). But a form would work too, and without the need for JavaScript.

    Devin Crane wrote:If I change the 2nd servlet-name to 'add' and the servlet-pattern is '/addServlet', wouldn't I call addServlet from the form's action with "/add/addServlet"?

    Where's the /add/ prefix coming from? That's just making up stuff. The prefix should be the context path, which is the same for all paths. See follows:

    <form action="/addServlet" method="get">

    Should be action="${pageContext.request.contextPath}/addServlet"

    The context path is always needed.

    By the way, I don't like the path "/addServlet". It makes it sound like you'll be adding a servlet. I don't like the word "servlet" to appear in the paths either -- that's an implementation detail. What does the servlet actually do? If it displays the add form page, how about something like "/displayAddForm"?

    <servlet-class>test.addServlet</servlet-class>

    Follow conventions. Class names start with a capital letter.
     
    Devin Crane
    Ranch Hand
    Posts: 32
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I was not making stuff up. I was just trying to follow the same pattern as /add/addServlet, and I couldn't remember what the context path was.
    I definitely would never have guessed to use ${pageContext.request.contextPath}. Google wasn't helping.
    But it works now, thanks!

    You're right, class names do, by convention, start with a capital letter, one convention I'm bad at remembering. I make methods more than I make classes so camelcase is on my mind more.

    Devin
     
    Bear Bibeault
    Author and ninkuma
    Marshal
    Posts: 65833
    134
    IntelliJ IDE Java jQuery Mac Mac OS X
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Devin Crane wrote:I was not making stuff up. I was just trying to follow the same pattern as /add/addServlet, and I couldn't remember what the context path was.

    I could not tell where that was coming from.

    I definitely would never have guessed to use ${pageContext.request.contextPath}.

    You need to read through the ServletsFaq and JspFaq. All sorts of good information is there that's better than random googling.

    In particular read about the types of paths and how to form resource URLs.

    You're right, class names do, by convention, start with a capital letter, one convention I'm bad at remembering. I make methods more than I make classes so camelcase is on my mind more.

    It gets easier with practice. A syntax-highlighting IDE can also be helpful.
     
    Devin Crane
    Ranch Hand
    Posts: 32
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Well, I got it working, thanks for your help!
    It now starts out showing me the whole database, and gives me a button that directs me to another page with a form to add to the database.
    Once submitted, it redirects again to display the whole database with the new info, again with the add button.

    I'm just considering redirecting from the servlet that inserts a row into the database to the orginal servlet that displays everything so as to not duplicate code.

    Devin
     
    Bear Bibeault
    Author and ninkuma
    Marshal
    Posts: 65833
    134
    IntelliJ IDE Java jQuery Mac Mac OS X
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Code duplication should be avoided. And it is a good practice to separate task controller code from page controller code.
     
    Devin Crane
    Ranch Hand
    Posts: 32
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    In trying to avoid duplication in my SubmitForm.java, I grab the values to insert into the database, create the mysql statement and execute it.
    I know this part works because when I go back to my original servlet, the new values are displayed.

    This is my code to redirect to my original servlet to display the db info:



    But I get:
    HTTP method POST is not supported by this URL
    , which url in the browser says:
    http://localhost:8080/hello/submitForm

    I've edited my web.xml for my SubmitForm servlet to allow POST methods:



    I'd have thought a servlet that can receive POST calls can invoke another servlet that doesn't. My logs don't show anything.

    Any ideas?

    Thanks,
    Devin
     
    Bear Bibeault
    Author and ninkuma
    Marshal
    Posts: 65833
    134
    IntelliJ IDE Java jQuery Mac Mac OS X
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Devin Crane wrote:
    This is my code to redirect to my original servlet to display the db info:



    That's not a redirect; it's a forward. Big difference. The transition between a task controller and a page controller should be a redirect. That breaks the request into two. Please read this article again and focus on the PRG pattern description.

    I'd have thought a servlet that can receive POST calls can invoke another servlet that doesn't

    Not with a forward.

    Any ideas?

    Use a redirect, not a forward.
     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!