Showing posts with label pet store. Show all posts
Showing posts with label pet store. Show all posts

Sunday, December 11, 2011

Java Pet Store 2.0 - the architecture (part 1)

To my surprise, the Java Pet Store 2.0 page, even though recently updated, still doesn't mention much about the design of the application.
So here we go, below you find some diagrams and explanations over how it's built and how it works. I'll continue the story in future posts, here I start with the overview and show how the catalog gets displayed.

First, check out this part of the web.xml file:

<servlet>
        <display-name>ControllerServlet</display-name>
        <servlet-name>ControllerServlet</servlet-name>
        <servlet-class>com.sun.javaee.blueprints.petstore.controller.ControllerServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ControllerServlet</servlet-name>
        <url-pattern>/catalog</url-pattern>
    </servlet-mapping>

It tells that the ControllerServlet needs to be used for URLs that match the pattern "/catalog".
For example, when following the link "Dogs" on the main page, we navigate to:
http://localhost:8087/petstore/faces/catalog.jsp?catid=Dogs
(I have Glassfish running on localhost:8087)
Since this matches the "/catalog" pattern, ControllerServlet.service() is triggered, as shown in Figure 2.
The ControllerServlet implements the FrontController J2EE pattern and delegates to various actions (see Figure 1 and Figure 2), depending on the servlet path. In this case the servlet path is "/catalog" and it maps to CatalogXmlAction. The latter reads the "command" parameter from the request and, because this one is "categories", it calls the CatalogFacade to get the categories via JPA (note in Figure 1 that "Category" is a JPA Entity).


Figure 1: The main entities involved in fetching the catalog

Figure 2: Displaying the catalog

The CatalogXml action, once it has the categories, it writes them to the response (HttpServletResponse) in JSON format (see below).
So how come, given this JSON format, the categories and the pets are so nicely displayed in the page (see Figure 3) still ?  Well, this is done with a bit of Dojo/JavaScript magic. 


[{"id":"CATS","catid":"CATS","name":"Cats","description":"Loving and finicky friends","imageURL":"cats_icon.gif",
"products": [{"id":"feline01","catid":"CATS","name":"Hairy Cat","description":"Great for reducing mouse populations",
"imageURL":"cat1.gif"},{"id":"feline02","catid":"CATS","name":"Groomed Cat","description":"Friendly house cat keeps you 
away from the vacuum","imageURL":"cat2.gif"}]},
etc.
]




Figure 3: The Pet Store application - after choosing the categories

Take a look at catalog.js, which is used in catalog.jsp to format the page:

function loadAccordion () {
        // go out and get the categories
        // this should be made more geric
        var bindArgs = {
            url:  applicationContextRoot + "/catalog?command=categories&format=json",
            mimetype: "text/json",
            load: function(type,json) {
               ac.load(json);
               processURLParameters();
             },
             error: ajaxBindError
        };
        dojo.io.bind(bindArgs);
    }


This method is called from initCatalog() in catalog.js, which in turn is called in catalog.jsp:

<script type="text/javascript">
    dojo.event.connect(window, "onload", function(){initCatalog();});
</script>


Finally, loadAccordion() calls ac.load(json) and ac.showCategory(params.catid), where "ac" is AccordionMenu() (the menu with categories in Figure 3), which again, sends us to:


this.load = function(lcategories) {
        categories = lcategories;
        // create all the rows
        for (var l=0; l &lt; categories.length; l++) {
            var row = createRow(l,"accordionRow", ITEM_HEIGHT);
            createLinks(row.div, categories[l].name, l, "accordionLink");
            divs.push(row);
        }
    }

Here, createLinks() makes the links on the left-hand side menu ("Cats", "Dogs", etc.), using categories[l].name as parameter. "Categories" come from the JSON shown above, retrieved in loadAccordion(): url:  applicationContextRoot + "/catalog?command=categories&format=json".

this.showCategory = function(catid) {
        for (var l=0; l < categories.length; l++) {
            if (catid == categories[l].name) {
                // now tell the scroller to load the first product
                initiateExpansion(l);
                if (categories[l].products[0]) {
                    dojo.event.topic.publish("/catalog", {type:"showProducts", productId:categories[l].products[0].id});
                } 
                break;
            }
        }
    }

Notice here "type" and "productId" labels. Back in catalog.js, we do:
dojo.event.topic.subscribe("/catalog", this, handleEvent);

So here we subscribe to the "/catalog" events with the callback "handleEvent", which does:

else if (args.type == "showProducts") {
          is.reset();
          populateItems(args.productId, 0, 0, true);
      }


Here, args.type is the label "type" we published above and args.productId is the label "productId". With the argument args.productId, "populateItems()" displays the images, etc. In order to do that, it uses DOM fields from catalog.jsp, e.g.:


var targetElement = document.getElementById("bodySpace");

To be continued ....


Sunday, November 21, 2010

Debugging Java PetStore with Glassfish and Eclipse

Once I made PetStore work in Glassfish, I wanted to debug it in Eclipse.

1. I ran asadmin in my application server path:
C:\J2EE\Sun\AppServer\bin>asadmin start-domain

2. In the browser, I ran the application server Admin Console, available in my case at localhost:4848

3. I went to Application Server menu (top left), I chose JVM Settings and I enabled Debug

4. I restarted the Application Server (after enabling Debug and saving this configuration, I noticed the link "Restart needed" top left; I clicked on it, after that I ran asadmin start-domain from the console)

5. I also ran asadmin start-database to start the database for PetStore

6. I started Eclipse (I use version 3.4.1); under Run menu, I chose "Debug configurations ...."; then I chose the PetStore project (which I had created previously in Eclipse) and port 9009 (the default port where Glassfish is listening for debuggers); I also enabled "Allow termination of remote VM"

7. Just for the test, I put a breakpoint in ImageAction.java, method service; then I started the debug configuration created at bullet 6; finally, I navigated in a browser to
 http://localhost:8087/petstore/faces/catalog.jsp
and I clicked a dog under Pets; I could see my breakpoint being hit.

Sunday, September 5, 2010

Making Java PetStore work

Recently I've been struggling with making the Pet Store 2.0 application work.
So, shortly, what I've done:
-  downloaded the jar from https://blueprints.dev.java.net/petstore/
-  downloaded Glassfish v2.1.1 from https://glassfish.dev.java.net/

Then I tried to deploy and run the Pet Store by running the following commands:
- in the application server directory /bin: 
asadmin start-domain
asadmin start-database

- in the Pet Store demo directory C:\J2EE\PetStore\latest\javapetstore-2.0-ea5:
ant setup
ant run


Even though all commands were successful, the application won't start. More specifically I got the error "The requested resource () is not available" when navigating to http://localhost:8087/petstore.

So, without further ado, these are the steps I've performed to make it work.

1. in C:\J2EE\PetStore\latest\javapetstore-2.0-ea5\bp-project\build.properties I corrected the following variables:
a. javaee.home to point to my application server: c:/J2EE/Sun/AppServer
b. javaee.server.username to point to my username (the one I used when I installed Glassfish)
c. javaee.server.passwordfile to point to ${javaee.home}/samples/passwordfile

2. I created the file "passwordfile" under c:/J2EE/Sun/AppServer/samples containing a single line:
 AS_ADMIN_PASSWORD=myPassword (the password I chose when I installed Glassfish)


3. I also updated the file app-server.properties in C:\J2EE\PetStore\latest\javapetstore-2.0-ea5\bp-project with javaee.home=c:/J2EE/Sun/AppServer

At this point, I got the Pet Store demo running on the Glassfish server (after running again "ant setup" and "ant run"). However, only the first page was properly shown (http://localhost:8087/petstore/) and as soon as I navigated to "Enter the Store" (http://localhost:8087/petstore/faces/index.jsp), I saw a blank page.



Note: instead of running "ant run", you can also deploy the petstore.war from the /dist directory (or from /build) by using the Glassfish admin console:

 










By looking at the logging of the "ant setup" command I noticed that there was some issue with the username/password when trying to install the connection pool. I could also see this by inspecting the Glassfish log files (in the admin console, at http://localhost:4848/). So, I've done the following:

4. instead of relying on the ant script to install the connection pool and the data source (i.e. the ant setup command), I installed them by hand using the Glassfish admin console; see below the general properties of the connection pool:





 








Also, note the "Additional Properties":













Here I had to add the following properties: 
- Password with the value APP (I know this from the file app-server.properties, see 3),
- DatabaseName with the value petstore (I found this by googling the web)

At this point if you click Ping under the General tab, you should get the message "Ping succeeded".


5. I also installed the data source (using the Glassfish admin console), which I called jdbc/PetstoreDB (I know this from the web.xml file):













Finally, I could navigate to http://localhost:8087/petstore/faces/index.jsp and got the Pet Store demo working properly ! (of course, don't forget to start the DB server and the application server by running:
asadmin start-domain
asadmin start-database
)