Dec 23, 2010

java.lang.VerifyError caused by Play-Morphia

It comes out intermittently and shows something like:
Exception in thread "main" java.lang.VerifyError: (class: models/NodeDelta, method: findById signature: (Ljava/lang/Object;)Lplay/modules/morphia/Model;) Wrong return type in function
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)
at java.lang.Class.getDeclaredMethods(Class.java:1791)
at com.google.code.morphia.utils.ReflectionUtils.getDeclaredAndInheritedMethods(ReflectionUtils.java:115)
at com.google.code.morphia.utils.ReflectionUtils.getDeclaredAndInheritedMethods(ReflectionUtils.java:98)
at com.google.code.morphia.mapping.MappedClass.discover(MappedClass.java:131)
at com.google.code.morphia.mapping.MappedClass.(MappedClass.java:110)
at com.google.code.morphia.mapping.Mapper.addMappedClass(Mapper.java:139)
at com.google.code.morphia.Morphia.map(Morphia.java:55)
at play.modules.morphia.MorphiaPlugin.afterApplicationStart(MorphiaPlugin.java:166)
at play.Play.start(Play.java:440)
at play.Play.init(Play.java:274)
at play.server.Server.main(Server.java:131)

Something is wrong obviously in the bytecode enhancer. But I just can't figure it out until i noticed the line of code:
CtMethod findById = CtMethod.make("public static Model findById(java.lang.Object id) { return mf.findById(id); }",ctClass);

Where mf is an instance of play.db.Model.Factory, and method play.db.Model.Factory#findById return an instance of play.db.Model, while actually a play.modules.morphia.Model is expected. Changing the line to the follows fixed the VerifyError:
CtMethod findById = CtMethod.make("public static Model findById(java.lang.Object id) {return (Model)mf.findById(id); }",ctClass);

Dec 15, 2010

Create a hierachical navigator in IBM Lotus WCM

I googled for long time for a solution that could produce hierarchical unordered list corresponding to site areas. Something like:
<ul>

<li>A
<ul>
<li>A.1</li>
<li>A.2</li>
</ul>
</li>

<li>B
<ul>
<li>B.1</li>
<li>B.2</li>
<li>B.3
<ul>
<li>B.3.1</li>
<li>B.3.2</li>
<li>B.3.3</li>
</li>
</ul>
</li>

</ul>


I follow the method introduced here. However I found it does not work out the whole hierarchies. I guess the NAV--SubNavigation with StartType equals to "Current Site Area" prevent it from happening.

The final solution is to use navigator to generate a linear list of nodes and use javascript to reconstruct the hierarchies.

Here is navigator definition:

Start Type: selected
Include Start: false
Ancestor Level: none
Descendant Level: All (or choose the level of hierarchies you want)
Preceding Siblings Level: none
Next Siblings Level: none
Show Site: false
Show content: false
Expand current navigator branch one level: false
Expand navigator to display current site area: false
Results per page: 1000 (or choose a number that is larger than the maximum items)
Start page: 1
Maximum pages to include: 1000 (or choose a number large enough)
Pages to read ahead: 1000 (or choose a number large enough)
Distinguish items with no children using the final navigator result design: false
Header: <url>
Footer: </ul>
Separator:
Navigator result design 1:
<li class="l1" id="<Placeholder tag="idnum"/>"><a href="<Placeholder tag="href"/>" target="_self" title="<Placeholder tag="Title"/>"><Placeholder tag="Title"/></a></li>

Navigator result design 2:
<li class="l2" id="<Placeholder tag="idnum"/>"><a href="<Placeholder tag="href"/>" target="_self" title="<Placeholder tag="Title"/>"><Placeholder tag="Title"/></a></li>

Navigator result design 3:
...

And this navigator gives the following html code:
<ul>
<li class="l1">A</li>
<li class="l2">A.1</li>
<li class="l2">A.2</li>
<li class="l1">B</li>
<li class="l2">B.1</li>
<li class="l2">B.2</li>
<li class="l2">B.3</li>
<li class="l3">B.3.1</li>
<li class="l3">B.3.2</li>
<li class="l3">B.3.3</li>
</ul>


Now it's javascript's work. In order to re-constructure the hierarchies, I write the following codes:

function process(level) {
var sel = 'li.l' + (level - 1);
jQuery.each(root.children(sel), function(id, el){
var pe = jQuery(this);
var dock;
var nl = pe.nextUntil(':not(li.l' + level + ')');
jQuery.each(nl, function(id, el){
if (!dock) dock = getDock(pe, level - 1);
jQuery(el).appendTo(dock);
});
});
}

function getDock(pe, level) {
var ul = pe.children('ul');
if (ul.size() == 0) {
ul = jQuery('<ul class="l' + level + 'ul"></ul>').appendTo(pe);
} else {
ul = ul[0];
}
return ul;
}

var root = null;
jQuery(function(){
root = jQuery('#ul'); //you should update #ul accordingly
jQuery.each([5,4,3,2], function(id, val){process(val)});
});


Now a good rendered hierarchies presented in my final html page.