Tuesday, June 30, 2009

Apache Wicket - How to run and get response from JavaScript

If you dont know what is Wicket - you are realling missing something. It is a b'ful framework from Apache which will make our life very much easier when doing web application development.
You can read more about Apache Wicket here

Here let us check how to invoke Javascript from a Wicket component and how receive/handle response. Assume the requirement is having a webpage where we will load some control using Javascript(For example - Google Earth ;) ) , and once the javascript execution is completed the page should do something.

01 public class MyPage extends WebPage {
02 /**
03 * Def constructor.
04
05 */

06 public MyPage() {
07 //
08 // Create and add a panel.
09 final JSPanel panel = new JSPanel("jsPanel");
10 panel.setOutputMarkupId(true);
11 add(panel);
12 }

Here we are creating a webpage and adding a panel to that. The panel is the place where we will
display the GoogleEarth through loading JavaScript.

But before going to the panel let us check how to get a call back from the JavaScript.
For acheiving this we will add an AjaxBehavior to the panel

01 public MyPage() {
02 ...
03 //
04 // Add an Ajax behaviour, this will be called by the javaScript
05 // when the streaming is completed.

06
final AbstractDefaultAjaxBehavior behave = new AbstractDefaultAjaxBehavior() {
07 protected void respond(final AjaxRequestTarget target) {
08 //
09 // Read the parameters send by JavaScript
10 Map map = ((WebRequestCycle)RequestCycle.get()).getRequest().getParameterMap();
11 Set keys = map.keySet();
12 Iterator it = keys.iterator();
13 while(it.hasNext()) {
14 String key = (String) it.next();
15 String[] value = (String[]) map.get(key);
16 }
17 }
18 };
19 panel.add(behave);
20 }


Curresponding html files are simple enough.

Now lets look at the JSPanel. Here we need to call the javascrip onLoad of the page. This is acheived through RenderHead method.


01 public class JSPanel extends Panel implements IHeaderContributor {
02 /**
03 * Def constructor.
04
05 */

06 public GEPanel(String id) {
07 super(id);
08 }

09
public void renderHead(IHeaderResponse response) {
10 //
11 // Check the behavior to get the callback URL
12 List list = getBehaviors();
13 String url = "";
14 if (list != null && list.size() > 0) {
15 AbstractDefaultAjaxBehavior beh = (AbstractDefaultAjaxBehavior) list.get(0);
16 url = beh.getCallbackUrl().toString();
17 }
18 String methodCall = "Your JS Method call";
19 response.renderOnLoadJavascript(methodCall);
20 }
21 }


Lets look at the relevant javascript now

function init(urlVal) {
url = urlVal;
//
//Create an instance of GE.
google.earth.createInstance("map3d", initCallback, failureCallback);
}

function initCallback(object) {
//
// Show GE and move camera to decired location.
ge = object;
ge.getWindow().setVisibility(true);
var lookAt = ge.getView().copyAsLookAt(ge.ALTITUDE_RELATIVE_TO_GROUND);
...
ge.getView().setAbstractView(lookAt);
...
//
// Make a call to the wicket callback url from here
var arg = "&key=" + value;
var wcall = wicketAjaxGet(url + arg , function() { }, function() { });
}

That is it. Let me know if you need the complete sample code for this.

Java code displayed as html here is using a tool HTML4Java, you can check it here http://www.toolbuddy.org/html4java.htm








Saturday, June 20, 2009

Capturing Image From Google Earth


Please note that images from Google Earth may be copy right protected, so you should carefully check before using such images.

Easiest way is - if you have a stand alone Google Earth application, start it and move to the decired location. This can be done through opening a KML file. Then use a screen capture program to take the screen shot (Or just use PrintScrn button)

What if there is no stand alone application available? Google static maps comes to the rescue.
Just load the url in a browser it will load the curresponding image.

Let us see how to do this from Java .

Use a url string.

String url = "http://maps.google.com/staticmap?center=%LAT%,%LON%&zoom=%ZOOM%&size=512x512&maptype=satellite&key=%KEY%";
Replace the place holders
%LAT% - Latitude
%LON% - Longitude
%ZOOM% - Zoom level
%KEY% - Google map key

//
// Load the image from url.
url = new URL(uri);
BufferedImage bi = ImageIO.read(url);
ImageIO.write(bi,"PNG",new File("image.PNG"));









ServiceMix MessageExchange memory leak


Are you observing memory leak in JBI components deployed in ServiceMix? First place to check will be whether the message exchanges are closed properly.

In the InOut message exchanges, after receiving message from provider , consumer should set the status as DONE in the exchange and again send it to provider.

Note - just setting the status to DONE is not enough , it must be send back to provider, otherwise the message exchanges will not be properly closed and will result in a memory leak.

E.g.-
inOutexchange.setStatus(ExchangeStatus.DONE); context.getDeliveryChannel().send(inOutexchange);

Memory leak in Java application


What are the first steps to do when notice that the newly developed Java application is not running continuously? Most of the time it may be due to memory leak.

First thing to do is study the memory usage/ thread creation patterns of the application. Different profiler tools are available in market for this.

Two tools I commonly use are
1. JProfiler
2. YourKit

In JProfiler - if there are memory leaks , total memory of the objects (which are leaking) will be shown against the class which created the memory.
Sometimes this may be misleading as the object references may be held by someone else , and that class is the real reason for the leak.

In my experience , identifying those classes were bit easier in YourKit.



Taking ScreenShot (PrintScreen) in Java

It is pretty easy to take a screen shot from Java code

Try
Rectangle rect = new Rectangle(0, 0, 700, 500);
BufferedImage screencapture = new Robot()
.createScreenCapture(rect);

// Save as JPEG
File file = new File("FileName.Jpg");
ImageIO.write(screencapture, "jpg", file);


Interesting question is what will happen if this code is executed in an environment where display devices are not available? You will get an AWT exception indicating "headless environment".

Getting position of HTML component

What if we want to read position of a html control in Javascript?
Only time I tried this was to get a screenshot of a particular area in the page, I doubt whether there is any valid usecases.
Try using the below function in JS

function getPositionOfElement(elemID) {
var offsetTrail = document.getElementById(elemID);
var offsetLeft = 0;
var offsetTop = 0;
while (offsetTrail) {
offsetLeft += offsetTrail.offsetLeft;
offsetTop += offsetTrail.offsetTop;
offsetTrail = offsetTrail.offsetParent;
}
return { left: offsetLeft, top: offsetTop };
}
Possible usage
getPositionOfElementElement('div_id').left;
getElementPosition('div_id').left;
Dont forget to check the properties like
self.screen.height
self.screen.availHeight
self.screenTop