Thursday, March 14, 2013

Java MVC with MongoDB and Morphia part 3

Hi, this is Ross. I made some changes to my name list website, and I thought I should share the changes.

The first thing I did was split the method in my service class. The code that added the data is now separate from the code that generates the name list. I also added logic that prevents exact duplication of entries. Here is the new AddName method:


        private static String database = "mvcmongo3";
        private static String collection = "names";
        
        public static String AddName(String first, String last)
            throws UnknownHostException {
            
            MongoClient client = new MongoClient();
            DB db = client.getDB(database);
            DBCollection coll = db.getCollection(collection);
            Name name = new Name();
            name.setFirstName(first);
            name.setLastName(last);
           
            BasicDBObject query = 
                new BasicDBObject("firstName", first).append("lastName", last);
            int count = coll.find(query).count();
            String message = null;
            if (count > 0) {
                message = first + " " + last + " is already on file";
            } else {
                message = first + " " + last + " is now on file";
                Morphia morphia = new Morphia();
                DBObject jname = morphia.toDBObject(name);
                coll.save(jname);
            }
            client.close();
            return message;
            
        }

As you can see, I build a JSON object with just the entered data, called "query".  

int count = coll.find(query).count();

counts the number of documents whose data matches the input. As you can see, this version of AddName returns a string that reports the results of that query. If no match is found, the input is added to the document collection. Here is the new function:


        public static ArrayList<Name> ListNames()
            throws UnknownHostException {
        
            MongoClient client = new MongoClient();
            DB db = client.getDB(database);
            DBCollection coll = db.getCollection(collection);
            DBCursor cursor = coll.find();
            ArrayList<Name> list = new ArrayList<Name>();
            for (DBObject b : cursor) {
                Morphia morphia2 = new Morphia().map(Name.class);
                BasicDBObject basic = (BasicDBObject)b;
                Name name2 = morphia2.fromDBObject(Name.class, basic);
                list.add(name2);
            }
            client.close();
            return list;
      }

As before, an argument-less query retrieves the entire collection. Morphia then translates each document into the Java class "Name", and adds the converted object to the list. As you can guess, I changed the controller, too...


    @Override
     protected ModelAndView onSubmit(
     HttpServletRequest request, 
     HttpServletResponse response, 
     Object command, 
     BindException errors) throws Exception {
         HttpSession session = request.getSession(true);
         Name name = (Name) command;
         ModelAndView mv = new ModelAndView(getSuccessView());
         mv.addObject("message", nameService.AddName(name.getFirstName(),
                 name.getLastName()));
     //    mv.addObject("nameList", nameService.ListNames());
       session.setAttribute("nameList", nameService.ListNames());
     //Do something...
     return mv;
     }

Now I create a session. Instead of adding the name list directly to the ModelAndView, I add it to the session. I made that change to make it easier for JSP to find the list. My code adds the string from AddName the old way. I didn't change the form view, but I did change the "success" view by creating success2View.jsp. I changed a controller's constructor's line to

setSuccessView("success2View"); 

I also added the following namespace to the controller:

import javax.servlet.http.HttpSession;

Here is the new view...


<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@page session="true" import="java.util.ArrayList, controller.*" %>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Success Page</title>
    </head>
    <body>
        <p>${message}</p>
        <h1>Name List</h1>
        
        <ul>
            <% for (Name name : (ArrayList<Name>)session.getAttribute("nameList")) { %>
            <li><%= name.getFirstName() %>&nbsp;<%= name.getLastName() %></li>
            <% } %>
        </ul>
    </body>
</html>

You can see I use standard JSP code now instead of JSTL. I retrieve the "nameList" session variable and cast it to ArrayList<Name>. The new view now shows whether or not the entered name was added to the database, as well as all the names in the collection as before. Note I use the getters in the Name class. I also import the ArrayList class in addition to the Name class. Note that it's more obvious what's going on. That "for" syntax is Java's "for-each". 

That concludes the changes I made. I plan on writing a more elaborate website using this stack. If I succeed, you'll probably hear about it. Thanks for reading and God bless!












No comments:

Post a Comment