Jdec 2.0 is Released…

As stated in my earlier blogs, I have made a release in sourceforge.net updating jdec to support JAVA 5 features namely :

  • Generics.
  • Annotations.

Users can grab this version from here.

Also was just able to cover some few bug fixes – not many. I just feel that decompiler is getting more and more complicated to cover all bug fixes. The only thing I see myself working on in next release is – inner classes. Right now the code doesn’t look so nice with all those dollar signs. Exact reversal of inner classes – including anonymous ones will make jdec output more beautiful and improve readability

As usual, any feedbacks/issues w.r.t enhancement are welcome – these i may address asap.

Categories: java, java 5, jdec, open source

Jdec and Java Annotations support

Heres a sample code with Java Annotations.

See Earlier Post for more details.

// Decompiled by jdec
// DECOMPILER HOME PAGE: jdec.sourceforge.net
// Main HOSTING SITE: sourceforge.net
// Copyright (C)2006,2007,2008 Swaroop Belur.
// jdec comes with ABSOLUTELY NO WARRANTY;
// This is free software, and you are welcome to redistribute
// it under certain conditions;
// See the File ‘COPYING’ For more details./**** List of All Imported Classes ***/

import java.lang.Object;
import java.util.ArrayList;

// End of Import

class AnnotationTest

{

/***
**Class Fields
***/

@TestAnnot(by = {1,2},obj = {java.lang.Object.class},e = en.TWO)

private Object obj ;
private List l ;

// CLASS: AnnotationTest:
AnnotationTest( )
{

super();
ArrayList JdecGenerated7 = new ArrayList();
this.l =JdecGenerated7;
return;

}
@StringAnn(ss = “gg”)

// CLASS: AnnotationTest:
public Object getObj(@SomeAnnot(bt = 2,name = {“Lhello;”,”sting2″},sh = 5,clzAr = {java.lang.String.class,java.util.Map.class},clz = java.lang.StringBuffer.class) Object o)
{

return this.obj;

}

}

Jdec and Java Generic Support

Well here goes –

(See Earlier Post for more details)

Sample class with generic support decompiled by jdec

// Decompiled by jdec
// DECOMPILER HOME PAGE: jdec.sourceforge.net
// Main HOSTING SITE: sourceforge.net
// Copyright (C)2006,2007,2008 Swaroop Belur.
// jdec comes with ABSOLUTELY NO WARRANTY;
// This is free software, and you are welcome to redistribute
// it under certain conditions;
// See the File ‘COPYING’ For more details.

/**** List of All Imported Classes ***/

import java.lang.Object;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
// End of Import

class<E extends java.lang.Object> GenericTestWithJdec {

Class<?>[] genericClassArrayField ;

GenericTestWithJdec( ) {

super();
return;

}

public Object returnComplexMap( ) {

Map<E,java.util.Map<java.lang.String,? extends java.lang.Object>> clone= null;
return clone;

}
public <T extends Result> Result doSomeStuff( Collection<?> c, Collection<java.lang.String> c2, ArrayList<java.util.HashMap> allMaps) {

Iterator<?> e= null;
List<? extends java.util.Map> mapList= null;
List<T> keySet= null;
mapList=allMaps;
keySet=null;
e=c.iterator();
Result JdecGenerated16 = new Result();
return JdecGenerated16.setRes(1000.0);

}

}

Java 5 support in Jdec – Finally !

What a relief - I can probably claim now quite confidently that Jdec support Java 1.5 important features- namely :

  1. Annotation support
  2. Generic Support (? How come- read on)

Annotation support – The class spec mentions both Runtime visible and invisible annotaitons at various levels :

  1. Class level
  2. Method level
  3. Method Parameter level
  4. Field level

I was able to add support for all these into jdec in the past couple of weeks.

Generic Support

Well, we know that generic are implemented by erasure. BUT the good part is that if the class is compiled with debug support, then jdec can give out better decompiled output by reading generic signature that is registered by the compiler in constant pool section of the class file.

This is how generic support has been implemented in Jdec. We know the saying right- somethings better than nothing.I will be posting some code sample of code decompiled by jdec in the following blogs

NOTE: The updated code is still not present in sf.net. I will make a release probably after few weeks when I have fixed many regular bugs in jdec.

Categories: java, java 5, jdec, jdk 5, open source Tags: , , ,

An Inspiring talk on climate crisis

ted.com is a site really worth visiting every now and then. If you havent been to this site, I suggest you do so.Take a break from the many many technical books – and this site is really awesome.

We all know the effort taken by Al Gore in the climate crisis issue. This talk he has given at TED is really wonderful and inspiring. Especially this line – “…dont tell me we dont have the capacity to do so…if we had one week’s worth of what we spend on Iraq war , then we have the capacity to do so” …Only thing is Bush should have been sitting in the audience.

Categories: General, climate

Released jdec 1.2.1

December 28, 2007 Swaroop Belur Leave a comment

Finally – another version is out. You can check it out here.

Again had to invest a lot of time to fix bugs found in 1.2.
(Really can understand now the commitment that is required to make frequent
releases)

There is one enhancement though – the ability to configure variable names if classes
were not compiled with debug info. At least now the code should read better.

This release focuses mainly on bug fixes. Still jdec doesn’t officially support 1.5
- though it attempts to decompile them anyway.
That should in all probability happen in next release.

Just like any open source project, user feedback is one definite way to improve
jdec. So if you use jdec and have found something which is not there
and which you would like to see in next release or there is some really
bad decompilation produced, please do drop me a line or report a bug .
This will surely go a long way in improving jdec.

Categories: java, open source

Using Laszlo javarpc approach + Spring Managed beans….

November 2, 2007 Swaroop Belur 7 comments

Off late, I am involved in porting some screens of an application built using Wicket + Spring + Hibernate
to Laszlo + Spring + Hibernate. To suggest that I would have been hesitant about it would not be
very far from truth..mainly because I love wicket.

However, as I checked out some sites built using Laszlo , my interest really grew.
In the past few days, I have playing around with javarpc part of Laszlo – since it gives
one the ability to use the service layer developed as is – all that is required is to build
a pojo which will access the service and return a list of java objects for example.

But as I started developing in OpenLaszlo javarpc approach, I thought I hit a dead
end regarding the approach to take to get my spring managed beans.After all that
was critical to invoke the service layer calls.Keep in mind that my remote pojo
was just really an ordinary java object.

The solution occurred when I was discussing this with my lead and it came to light
that Spring 2.0 has a lot of new features like @Configurable approach. However this
simply uses AspectJ under the hood. Also this approach suited me because
as we all know its all about getting beans injected instead of pulling explicitly.

With this in mind, I decided to implement using AspectJ. AspectJ is really powerful.
One is able to write fine-grained expressions to capture joinpoints.

So this is code that I finally got to use to make my javarpc approach working…

The base handler which stores reference to service – this is what needs to get injected…public abstract class BaseRemoteHandler implements Serializable {

private IService service;

private String serviceNameInContextFile;

public IService getService() {
return service;
}
public void setService(IService serive) {
this.service = serive;
}

public abstract String getServiceNameInContextFile() ;

public void setServiceNameInContextFile(String serviceNameInContextFile) {
this.serviceNameInContextFile = serviceNameInContextFile;
}

}


This is the ACTUAL remote handler – which laszlo will access
public class AttributeRemoteHandler extends BaseRemoteHandler{

public AttributeRemoteHandler() {
super();
}

@Override
public String getServiceNameInContextFile() {
return “attributeServiceManager”; // The name of service in the context file used by Spring.
}

public List getListAtrributes(int start,int count,String column,boolean ascending){
return ((AttributeService)getService()).getSortedAttributes(0, count, column, ascending);
}

}


Finally THE aspectj ASPECT – which does the magic required ….

public aspect ServiceInjector {

public pointcut instanceIdentifier(): execution(*.new(..));

before(): instanceIdentifier(){

Object thisobject = thisJoinPoint.getThis();

if(thisobject instanceof BaseRemoteHandler){

BaseRemoteHandler basehandler =((BaseRemoteHandler)thisobject);

String managedServiceName = basehandler.getServiceNameInContextFile();

if(managedServiceName == null){

throw new IllegalStateException(“Serive name not implemented in handler “+basehandler.getClass().getName());
}
org.springframework.context.ApplicationContext context =
ApplicationContextFetcher.getContext(); // ApplicationContextFetcher – My Util class to get ApplicationContext

Object service = context.getBean(managedServiceName);
basehandler.setService((IService)service);

}

}

}

Categories: AspectJ, Laszlo, Spring, openlaszlo

Weird compilation problem

Today as i was coding , I just happened to write this piece of code


public void test(int i){


   if(i > 1)
     int z=5;

}

For some reason, the compiler flags the above as error.

However the below works just fine…


public void test(int i){


   if(i > 1) {
       int z=5;
   }

}

Any idea here anyone??

Categories: java

Wicket behaviors to the rescue again !

July 8, 2007 Swaroop Belur 3 comments

Scenario :

In my application , pages showing information about an item in the form of a table is common. These tables include checkboxes for selecting the individual items – for tracking the items for any operation like deleting.

Assume that a user selects some checkboxes to perform the delete operation. Before the server request is sent, user is prompted by a javascript alert if he wishes to change his mind.

This is where the javascript cancel comes in and this is where the magic of wicket behaviors come in to save my day.
The issue:  To uncheck the checkboxes checked after the user clicks cancel in Javascript confirm window.

In my earlier blogs, I have mentioned how useful behaviors can be.Behaviors are wonderful things in wicket.
Not only can a wicket component receive a request (via a listener),but So CAN WICKET BEHAVIORS !!!

I will use the above concept to fix the above mentioned problem:
NOTE: before proceeding I would like to mention that there is more than one approach to fix a problem like this. BUT the important thing to remember is that , during the request sent after clicking the javascript cancel button , the data provider should not be fired again. This will happen if form containing the table is attached again.

So any solution should take care that of the above fact.In the solution I attempt here , I ensure that provider does not run again

Here the code
Step 1:

We need to store the mark up ids of checkboxes top uncheck later…

List <Long> toDeleteItems = new ArrayList<Long>();
List< String> toDeleteItemsMarkupIds = new ArrayList<String>();

Step 2 : Have a checkgroup in your page. The checkgroup here can be useful not just to support this solution , but also to act as a container to checkboxes for selecting/de-selecting all. Here it is there just to support the solution.

CheckGroup group = new CheckGroup(“group”,new Model());group.setOutputMarkUpId(true);

Step 3: Write the ajax behavior – this is where the magic happens.

AbstractDefaultAjaxBehvior resetBehavior = new AbstractDefaultAjaxBehvior (){

public void respond(AjaxRequestTarget target) {

 /*** First clear the item ids to delete ***/          
 toDeleteItems.clear();
 /*** Then add javascript to uncheck the   checkboxes in the UI ***/
  for(int z=0; z< toDeleteItemsMarkupIds.size();z++){
     String   js = "element=document.getElementById(‘"+toDeleteItemsMarkupIds.get(z)+"');";
     js=js  + "element.checked =   false;";

     target.appendJavascript(js);

   }

}

}

Step 4: Get the url to invoke:

group.add(resetBehavior);

/** Get the url to the behavior ***/

String cancelUrl = resetBehavior.getCallbackUrl(true false);

Now, a bit of stuff from wicket-ajax.js script

String fullUrl =”wicketAjaxGet(\’”+url+”\’, function() {} , function() {})”;

The above is required so that wicket can make an ajax request and the page wont change – just the checkboxes will be affected.
NOTE: window.location = url ; will not work as the browser will change the url to the behavior url which only sends back the checked status of some checkboxes and the page will then be lost.

Step 5 : Final step -:)

The delete button needs to have its onclick behavior modified slightly

Link deleteLink = ….

deleteLink.add(new SimpleAttributeModiefier(“onclick”,

“var v = confirm(‘Do you want to delete’) ;”+

“if(v == false) { fullUrl }” +

“return v;” ));

Categories: wicket

Growable wicket textarea…

We all know how painful it can get when we type quite a bit in a textarea in a web page , only to keep scrolling up every

now and then to see the entire content. In this blog , i will attempt to produce a growable textarea using wicket.

The purpose of this blog is NOT ONLY to demonstrate a growable textarea BUT MAINLY to illustrate how

powerful wicket behaviors are.( Also how easy it is to use them).

Behaviors are wonderful value additions to wicket components themselves. As the name itself suggest, they add something

extra/value to the component they are binded to. For more information , have a look at the wiki page.

In this blog, I use an ajax behavior which does 2 things

1> updates the value

2> checks whether the textarea should grow or not

(only vertically not horizontally)

Another very interesting thing about these behaviors in wicket is that they can be triggered after every n

seconds – the value of n can be controlled by the user. This is amazingly useful as it will not overload the server.

So heres the code…

public class GrowableTextArea extends TextArea {

int initialRowSize = 1;

int fixedColSize = 40;

int currentRowSize = initialRowSize;

float temp = 1.0f;

String inputValue;

public GrowableTextArea(String id) {

super(id);

setModel(new PropertyModel(this,”inputValue”));

setOutputMarkupId(true);

add(new GrowableBehavior(“onkeyup”));

}

/***

Set the rows here. So that every time component is rendered,

rows value is updated.

**/

@Override

public void onComponentTag(ComponentTag tag){

super.onComponentTag(tag);

tag.put(“rows”,currentRowSize);

tag.put(“cols”,fixedColSize);

}

/*** Getters and setters ***/

public int getCurrentRowSize() {

return currentRowSize;

}

public void setCurrentRowSize(int currentRowSize) {

this.currentRowSize = currentRowSize;

}

public String getInputValue() {

return inputValue;

}

public void setInputValue(String inputValue) {

this.inputValue = inputValue;

}

}

/***BEHAVIOR – This is where the magic happens***/

private class GrowableBehavior extends AjaxFormComponentUpdatingBehavior

{

/***

Tell it to fire the onkeyup event every 1/2 sec.

**/

public GrowableBehavior(String event) {

super(event);

setThrottleDelay(Duration.milliseconds(500));

}

/***

First the model is updated and then

length is checked to see the

whether rowcount should be incremented

**/

@Override

protected void onUpdate(AjaxRequestTarget target) {

Component comp = getComponent();

TextArea textarea = (TextArea)comp;

String value = (String)textarea.getConvertedInput();

if(value != null){

int currentLength = value.length();

float f = (float)currentLength/fixedColSize;

if(f > temp){
currentRowSize++;

temp = temp +1;

target.addComponent(comp);
}

}

}
}

Categories: wicket

Cancel link and component errors

June 24, 2007 Swaroop Belur 3 comments

We all know how useful validators and ajax behaviors can be for showing errors
upfront to the user if some input is wrong for example. I have lost count how many
times i have had to use AjaxFormComponentUpdatingBehavior.
An immensely useful behavior.

Everything looks nice until a link called cancel link comes up. So basically what
do you do when someone comes up and says -

“hey, i dont want to see any error messages when i click cancel link” ???

Generally these update/check events happen when onchange/onblur javascript event gets fired.
So i spent some time during the weekend digging into wicket source code to find a way out.

I feel now that it is not really possible to prevent errors being shown in all
cases even if we throttle the ajax update events.(1 sec is reasonable,
but u still cannot prevent some error being shown before user clicks cancel)

Well, keeping the above in mind, I have come up with this solution.
This works as follows.
[NOTE: I have not used any throttling in my solution]

1. User enters a wrong input in a field .
2. He immediately clicks cancel. [ A change of mind by user]
3. Ajax update happens and registers the error
4. The ajax call decaorator checks which element had the last focus .
5. If it is cancel link, the class(css style) on feedback panel is set to
display:none/visibility:hidden;
6. Cancel link does its job and takes the user away from the current
screen w/o showing any error.

Code:

Step 1:: Create a feedback panel as

FeedbackPanel feedback = new FeedbackPanel(“feedback);
feedback.setOutputMarkupId(true);
add(feedback);

Step 2:: Lets say the cancel link is simply a page link as

Link cancel=new PageLink(“cancel”,SomePage.class);
cancel.setOutputMarkupId(true);
cancel.add(new SimpleAttributeModifier(“onfocus”,”return setCurrentFocus(‘”+cancel.getMarkupId()+”‘);”));

// The above line causes the browser to set a javascript variable to point to cancel
//when cancel is clicked.

Step 3: Say there is a TextField for which user has to enter input.

TextField ageField = new TextField(“age”, /*** Model ***/);
ageField.add(new UpdateBehavior(“onblur”));

Code for UpdateBehavior:

private class UpdateBehavior extends AjaxFormComponentUpdatingBehavior{//Say the valid age for age is more than 18 and
// user entered 10. And say a validator kicked in
// to register an error for the age field.[ Code for validator assumed]
// ask target to render the feedback
panel.@Override
public void onUpdate(AjaxRequestTarget target){
target.addComponent(feedback);
}


/** Now override call decorator ***/
@Override

protected IAjaxCallDecorator getAjaxCallDecorator(){

return new AjaxPostprocessingCallDecorator(new IAjaxCallDecorator(){
public CharSequence decorateScript(CharSequence script){return script;}
public CharSequence decorateOnSuccessScript(CharSequence script){ return script;}
public CharSequence decorateOnFailureScript(CharSequence script){return script;}

})

/*** THE IMPORTANT STUFF ***/

{
public CharSequence postDecorateOnSuccessScript(CharSequence script)
{
String hideScript = "if(focussed == 'cancel'){hideErrors();}";
return hideScript + script;
}

} // End of post call decorator
}

} 

// End of behavior

Now for the javascriptfunction setCurrentFocus(id){
focussed = id;
return true;
}

function hideErrors(){
var feedback = document.getElementById(“feedback”);
if(feedback != null) {

feedback.className = feedback.className.replace(‘visible_class’,'hide_class’);

}
}

Finally for the CSS:

.visible_class{
display:block;
visibility:visible;
}

.hide_class{
display:none;
visibility:hidden;
}

-Any feedback/suggestions to improve welcome .

Categories: wicket

Binding keyboard events to wicket component events

June 22, 2007 Swaroop Belur 3 comments

For quite some time now, i have been involved in a wicket project.
Believe me , its been all fun and learning all the way.
For those of you who are new to wicket, have a look a here

Here I would like to show a piece of code which will bind
keyboard events to component actions.

NOTE: Before actually beginning, i would like to state here that
this should be regarded as a first version which can be improved
further by modelling the javascript needed as behaviors.

Well, this is how it looks now…

Step 1 : Implement a method lets say buildComponentIdKeyValueMap() as

private void buildComponentIdKeyValueMap()

{
componentkeys.put("clear","45");
componentkeys.put("delete","46");
}

Here key is wicket id of component and value is value of some key pressed.
Example enter key as 13 and so on.

Step 2: Register the interested components as

private void buildInterestComponentList(){

interestedcomponents.add(“clear”);
interestedcomponents.add(“delete”);
}

NOTE: We can get these from the first method by calling keyset as well.

Step 3: Implement a method lets say buildInterestedComponentUrls() as
/***/
Iterates thru' the form components and gets hold of
intersted components and builds the url for them
by getting hold of thr listener they work on.
For example: Link implements ILinkListener

***/

private void buildInterestedComponentUrls()
{
form.visitChildren(new IVisitor() {

public Object component(Component component) {

String wicketid = component.getId();
if (!Strings.isEmpty(wicketid) && interestedcomponents.contains(wicketid)) {
if (component instanceof IRequestListener) {
IRequestListener componentListener = (IRequestListener) component
Class clazz = component.getClass();try {

Field requestListenerInterface = clazz.getField(“INTERFACE”);

RequestListenerInterface reqdInterface = (RequestListenerInterface)
requestListenerInterface .get(component);

componenturls.put(componentkeys.get(wicketid),component.urlFor(reqdInterface));
}
catch (SecurityException e) {}
catch (NoSuchFieldException e) {}
catch (IllegalAccessException e) {}
}
}
>return IVisitor.CONTINUE_TRAVERSAL;
}
});
}

Step 4 : Implement javascript support [ This requires fine tuning ...May be this

can be modelled differently using behaviors]
/***
Regsiters the onkeyup as the event to fire the call.

**/

private void buildJSMapForUrls()

{
StringBuffer buffer = new StringBuffer(“var map = new Object();”);
Iterator iterator = componenturls.entrySet().iterator();
while(iterator.hasNext()){
Map.Entry entry = (Map.Entry)iterator.next();
buffer.append(“map['"+entry.getKey()+"'] = ‘”+entry.getValue()+”‘;”);
}
form.add(new SimpleAttributeModifier(“onkeydown”,buffer.toString()+ “;”+triggerCall()));
}

private String triggerCall(){

return “document.getElementById(‘” + form.getMarkupId()
+ “‘).onkeyup = function (e) {\n”
+ “var evt = (e) ? e : window.event; \n”
+ “var keyCode = evt.keyCode;triggerKeyEvent(keyCode,map);\n};”;
}

Step 5: Finally include the javascript in ur html

<script>function triggerKeyEvent(code,map){var url = map;
if(url != null){
window.location.href = url;
}
else{
alert(“No url bound to key “+code);
}
}</script>
Categories: wicket