Sunday, October 31, 2010

JMX - Life Savior or Backdoor

The Java Management Extensions (JMX) API is a standard for managing and monitoring applications and services. Its usage in application build using Spring Framework is very simple and easy. I hope you'll agree with me after lecture of this post.

We will use one of the possible solutions for JMX and Spring usage, based on Java 5 annotations. On the Spring configuration level we need only one new line:

<beans xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" 
xsi:schemalocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context 
           http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    ...
    <context:mbean-export />
    ...
</beans>

The rest of this magic is done at the Java source :). Let's build a handler interceptor, which will be also exported as the managed bean:

@ManagedResource(objectName = "Test:name=Cerberus")
public class Cerberus extends HandlerInterceptorAdapter {

    private boolean opened = true;

    @ManagedOperation
    public void close() {
        this.opened = false;
    }

    @ManagedAttribute
    public boolean isOpened() {
        return opened;
    }

    @ManagedOperation
    public void open() {
        this.opened = true;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!opened) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
        }
        return opened;
    }

}

Suppose that we map this interceptor to some URL within our web application, check if the target URL will return some response ...

Wonderful! But wait, where can we see this managed bean? - you may say :) - sometimes you need the glasses to read the newspaper ;) - We will use the VisualVM as the glasses, which will help us to see the managed beans. When we run it, we will see something like this:
Now select the Tomcat on the left pane, and when the right one will display the tomcat information, choose MBeans (Managed Beans)
From the list of Managed Beans choose Test and then Cerberus - why? We named our bean this way :) - using: @ManagedResource(objectName = "Test:name=Cerberus"), now you should see:
We used the @ManagedAttribute only on isOpened method, therefore the opened attribute will be read only. Let's switch to the Operations tab, which contains:
As you see we can run from this tab 3 methods marked with @ManagedOperation or @ManagedAttribute annotations. Let's run the close method - click on the close button and following dialog will appear:
Let's check the opened attribute using isOpened method call:
Wonderful, but what does it mean to our handler interceptor? Let's try to reach the URL protected by our Cerberus again:
It looks like the Cerberus stopped the request, sending 404 error - as we asked him to do :)

Amazing and terrifying - you can control your application behavior from outside - use it with care ...

Thursday, October 21, 2010

JSON - Jackson Serialization Narrowed

In my last post - JSON - Jackson to the rescue - I've described quick example of JSON response creating. Let's back to this example and take a deeper look at the created response.

[{"id":1, "benefits":[{"name":"Healthy Employees", "id":1, "type":"HEALTH_COVERAGE", "startDate":1104534000000, "endDate":null}, {"name":"Gold Autumn","id":2,"type":"RETIREMENT_PLAN","startDate":1104534000000,"endDate":null},{"name":"Always Secured","id":3,"type":"GROUP_TERM_LIFE","startDate":1104534000000,"endDate":null}],"firstName":"John"},{"id":2,"benefits":[],"firstName":"Mary"},{"id":3,"benefits":[],"firstName":"Eugene"}]

There are situations, where parts of the data represented by domain entities should remain invisible for the public, and therefore shouldn't be serialized and exposed via JSON. We will try to narrow our response down to make it a little more secure from our point of view - by hiding the Employee's benefits.

First method to achieve this goal is usage of @JsonIgnore annotation.

@Entity
@Table(name = "EMPLOYEES")
public class Employee implements Serializable {
   ...
    @JsonManagedReference("employee-benefit")
    @OneToMany(mappedBy = "employee", cascade = CascadeType.PERSIST)    
    @JsonIgnore
    public List getBenefits() {
        return benefits;
    }
    ...
}

The above modification will change the response to:

{"employees":[{"id":1,"firstName":"John"},{"id":2,"firstName":"Mary"},{"id":3,"firstName":"Eugene"}]}

which is exactly what we need - but don't smile too wide yet ;) - consider situation when you want the same entity to be serialized in different ways depending on the request "context". It is very probable that you would like give to customer only the properties necessary in the response, while the admin should see much more in his part of application. @JsonIgnore is unusable in this case :( - but wait, don't panic yet - here we come to the second solution - @JsonView annotation

Let's modify the controller preparing the JSON response in the following manner:

@Controller
@RequestMapping("/employee-list.json")
public class EmployeeListController {

    private static final String MODEL_KEY_EMPLOYEES = "employees";

    @Autowired
    private EmployerDAO employerDAO;

    private final ObjectMapper objectMapper = new ObjectMapper();

    private final MappingJacksonJsonView view = new MappingJacksonJsonView();

    public EmployeeListController() {
        objectMapper.getSerializationConfig().setSerializationView(Employer.PublicView.class);
        view.setObjectMapper(objectMapper);
        view.setRenderedAttributes(new HashSet(Arrays.asList(MODEL_KEY_EMPLOYEES)));
    }

    @RequestMapping(method = RequestMethod.GET)
    public View handleGet(@RequestParam("employerId") Long employerId, Model model) {
        model.addAttribute(MODEL_KEY_EMPLOYEES, employerDAO.getEmployees(employerId));
        return view;
    }
}

As you see we will use the Spring Framework's MappingJacksonJsonView, with our own ObjectMapper instance. In controller's constructor we define which model attributes should be serialized (using setRenderedAttributes method), and switch serialization view to the Employer.PublicView. This will force Jackson to serialize only those properties which don't have @JsonView annotation at all, or have @JsonView annotations matching specified view. If we will modify our entities to look like this:

@Entity
@Table(name = "EMPLOYERS")
public class Employer implements Serializable {

    public interface PrivateView { }

    public interface PublicView { }
    ...
    @Column(name = "BUSINESS_NAME")
    @JsonView(PublicView.class)
    public String getBusinessName() {
        return businessName;
    }

    @JsonManagedReference("employer-employee")
    @OneToMany(mappedBy = "employer", cascade = CascadeType.PERSIST)
    @JsonView(PublicView.class)
    public List getEmployees() {
        return employees;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long getId() {
        return id;
    }
    ...
}

@Entity
@Table(name = "EMPLOYEES")
public class Employee implements Serializable {
    ...
    @JsonManagedReference("employee-benefit")
    @OneToMany(mappedBy = "employee", cascade = CascadeType.PERSIST)
    @JsonView(PrivateView.class)
    public List getBenefits() {
        return benefits;
    }

    @JsonBackReference("employer-employee")
    @ManyToOne(optional = false)
    @JoinColumn(name = "EMPLOYER_ID")
    public Employer getEmployer() {
        return employer;
    }

    @Column(name = "FIRST_NAME")
    public String getFirstName() {
        return firstName;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long getId() {
        return id;
    }
    ...
}

we will get exactly the same response as for @JsonIgnore usage, but in a little more flexible way :)

{"employees":[{"id":1,"firstName":"John"},{"id":2,"firstName":"Mary"},{"id":3,"firstName":"Eugene"}]}

The last possibility worth mentioning here is usage of mix-in annotations, let's change our controller once again to show the idea standing behind it.

@Controller
@RequestMapping("/employee-list.json")
public class EmployeeListController {

    @JsonIgnoreProperties("benefits")
    private static class EmployeePublicView extends Employee {
        // Empty by design ...
    }

    private static final String MODEL_KEY_EMPLOYEES = "employees";

    @Autowired
    private EmployerDAO employerDAO;

    private final ObjectMapper objectMapper = new ObjectMapper();

    private final MappingJacksonJsonView view = new MappingJacksonJsonView();

    public EmployeeListController() {
        objectMapper.getSerializationConfig().addMixInAnnotations(Employee.class, EmployeePublicView.class);
        view.setObjectMapper(objectMapper);
        view.setRenderedAttributes(new HashSet(Arrays.asList(MODEL_KEY_EMPLOYEES)));
    }

    @RequestMapping(method = RequestMethod.GET)
    public View handleGet(@RequestParam("employerId") Long employerId, Model model) {
        model.addAttribute(MODEL_KEY_EMPLOYEES, employerDAO.getEmployees(employerId));
        return view;
    }

}

As you see it is very similar to the controller above, the difference is new class EmployeePublicView extending Employee, and defining that benefits property will be ignored while serialization (using @JsonIgnoreProperties annotation). OK, but how this will help us with desired serialization of Employee instances? - the key factor is addMixInAnnotations usage - this method allows us to override the annotations defined on Employee class with those from the EmployeePublicView! Amazing and effective idea which doesn't need any domain entities modifications (you may safely remove the @JsonView annotations from the preview example)

Monday, October 18, 2010

JSON - Jackson to the rescue

Sometimes you have to fetch some data from the server in JavaScript, JSON is pretty good choice for this task.

Let's play with the Employer - Employee - Benefit example from the post JPA Demystified (episode 1) - @OneToMany and @ManyToOne mappings. We will use it inside the web application based on Spring Framework. Our first controller will return the employees list as the response body, in our case MappingJacksonHttpMessageConverter will be used automagically for converting the value returned by handleGet method to the response send to client.

@Controller
@RequestMapping("/employee-list.json")
public class EmployeeListController {
    @Autowired
    private EmployerDAO employerDAO;

    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    public List<Employee> handleGet(@RequestParam("employerId") Long employerId) {
        return employerDAO.getEmployees(employerId);
    }
}

When we try to fetch the data for the first time, we encounter beautiful exception: JsonMappingException: Infinite recursion (StackOverflowError) - caused by bi-directional references between the Employer - Employee - Benefit.

Looking for the possible solution, I've found a note Handle bi-directional references using declarative method(s), and after reading it, I've corrected the domain entities in following way:

@Entity
@Table(name = "EMPLOYERS")
public class Employer implements Serializable {
...
    @JsonManagedReference("employer-employee")
    @OneToMany(mappedBy = "employer", cascade = CascadeType.PERSIST)
    public List getEmployees() {
        return employees;
    }
...
}

@Entity
@Table(name = "EMPLOYEES")
public class Employee implements Serializable {
...
    @JsonManagedReference("employee-benefit")
    @OneToMany(mappedBy = "employee", cascade = CascadeType.PERSIST)
    public List getBenefits() {
        return benefits;
    }

    @JsonBackReference("employer-employee")
    @ManyToOne(optional = false)
    @JoinColumn(name = "EMPLOYER_ID")
    public Employer getEmployer() {
        return employer;
    }
...
}

@Entity
@Table(name = "BENEFITS")
public class Benefit implements Serializable {
...
    @JsonBackReference("employee-benefit")
    @ManyToOne(optional = false)
    @JoinColumn(name = "EMPLOYEE_ID")
    public Employee getEmployee() {
        return employee;
    }
...
}

After performing the above changes, I could finally enjoy the JSON response returned by my code:

[{"id":1, "benefits":[{"name":"Healthy Employees", "id":1, "type":"HEALTH_COVERAGE", "startDate":1104534000000, "endDate":null}, {"name":"Gold Autumn","id":2,"type":"RETIREMENT_PLAN","startDate":1104534000000,"endDate":null},{"name":"Always Secured","id":3,"type":"GROUP_TERM_LIFE","startDate":1104534000000,"endDate":null}],"firstName":"John"},{"id":2,"benefits":[],"firstName":"Mary"},{"id":3,"benefits":[],"firstName":"Eugene"}]

And as usual some links for the dessert:

Sunday, October 10, 2010

Geolocation API - Get Current Position

Look around :) - what are you doing here? how did you get here? and where the heck is "here"? I'll not be able to help you with the first two questions ;) - but the last one can be quickly answered with the Web Browser supporting the W3C Geolocation API.

Let's use following HTML:

<html>
  ...
  <head>
    ...
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js" ></script>
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false" ></script>
    <script type="text/javascript">
      var map;
      var mapCenter;
      var marker;
            
      function handleError(error) {
        alert('Error: ' + error.message + ' (' + error.code + ')');
      }
            
      function locationFound(position) {        
        // Center map on your location ...        
        mapCenter = new google.maps.LatLng(position.coords.latitude, 
                                           position.coords.longitude);
        map.setCenter(mapCenter);      
        // ... add new marker at map's center ...
        marker = new google.maps.Marker( 
                                { position: mapCenter, 
                                       map: map, title: "Your position" });    
      } 
         
      $(document).ready(
        function() {
          // Create new Google Map using the div having id 'map' ...
          map = new google.maps.Map($('#map')[0], 
                             {      zoom: 14, 
                               mapTypeId: google.maps.MapTypeId.TERRAIN });
          // ... check if your browser supports W3C Geolocation API ...
          if (navigator.geolocation) {
            // ... ask for current position ...
            navigator.geolocation.getCurrentPosition(locationFound, 
                                                     handleError);
          } else {
            alert("Geolocation not available");
          }
      });
    </script>
    ...
  </head>
  <body>
    <div id="map" style="width: 640px; height: 480px;"></div>
  </body>
</html>

I started with Google Chrome and when the above code has loaded in it, it asked first:


With trembling heart I pressed "Allow", and after few moments, I saw the desired position on map:


Don't ask me how they are able to track me down ;) - I can see some possibilities: black magic, IP number tracking, some hidden cameras, or electronic bugs in my apartment ;) - to discard the last possibility, I took my iPhone and went out for the stroll - and guess what ;) - when I opened the above page, iPhone asked me if I want to reveal my current position to the mobile Safari, and when I confirmed, showed me similar map view to the above ...

Some links for the dessert:
Which Devices Support Javascript Geolocation via navigator.geolocation?
How to Use iPhone JavaScript Geolocation
How to use the W3C Geolocation API (Opera)
Using geolocation (Firefox)

Monday, October 4, 2010

Web Application Profiling - Google's Speed Tracer

This is another cartoon post ;) This time about the Speed Tracer, a Google Chrome plugin which allows you to identify the problems related to User Interface of your Web Application.

When you run this tool on some URL you'll see a list of events with their timing:


Each event on the list can be expanded to see its details:


Speed Tracer identifies also potential problems related to the events:


Second tab - named "Network (resources)" presents the network traffic including files required for processing the page (like CSS, or JavaScript)


Selecting specific resource views its details, potential problems are marked with the badges in the resource list on the left, and described in details


Speed Tracer can be also integrated with Spring Insight (see my post Web Application Profiling - Spring Insight)


Interested? Try it yourself :) - I believe it can be helpful for tracking down UI performance problems.

Saturday, October 2, 2010

Web Application Profiling - Spring Insight

Are you writing Web Applications using Spring Framework? Have you ever thought what's going on under the hood? Why your application is responding so slowly? Why the snail outside your window is disappearing in the distance so fast while you still wait for your application response? You should :) and the Spring Insight can be very helpful with this task.

You should start with the tc Server Developer Edition which is in fact well known Apache Tomcat 6.0 on steroids ;). Then you should take a look at the Spring Insight - this tool is installed into tc Server as usual web application, and allows you to take a journey into your own application ;)

I'll put here only few screenshots of Spring Insight in the action, detailed information about installing and using tc Server along with the Spring Insight can be found on the Spring Source web pages.

Let's start ;)


When you click one of the bars on the chart you will see the details of request handling:


As you see on the screen request handling took 316 ms. Trace Detail section holds all methods which were executed during the request handling and all database queries which were performed. 


For each method/database call you can see the details like input parameters, SQL Query executed, or returned value (method only). Selecting request details will show you quick request summary along with request and response headers.

You may wonder why you see the database queries during the view rendering? As you know JPA's lazy loading defers loading the entities from database until they are used for the first time, and it happens during the view rendering. As you see on the above example, there are potential places for improvements (consider dropping lazy usage, use batch reading instead of one by one while fetching lazy entities).

Spring Insight offers you also some statistics about the used application resources - see Browse Resources at the top of page.


Of course you can see the details for each resource:


Summarizing this cartoon post :) - very interesting tool for all of the Spring Framework addicted developers - but in fact not only them - some parts of Spring Insight should be functional also for ordinary Servlet, or application written using some other framework. There is also possibility of writing your own Spring Insight plugins, so don't hesitate ;) use it and extend ;) - it is worth it