woensdag 26 september 2007

ldap on mac os x

to start openldap:
jdijkmeijer [/usr/libexec]$sudo ./slapd

apache directory studio:
localhost:389 anonymous binding.
to be continued.

Ok the continue: For some reason I could not get the openldap to work correctly slapadd etc all seemed to work but login in with the rootdn and password supplied, gave an error 49 invalid credentials. I do suspect the berkeley db is screwed but i'm not sure.
Anyhow I'm about to reinstall openldap hopefull that will work without installing the prefigured ldap /usr/libexec/slapd Im also woondering what will happen to the slap* cmds. Anyhow just installed the berkeleydb 4.6. It would have been nice if the installation script at http://www.oracle.com/technology/documentation/berkeley-db/db/ref/build_unix/intro.html
would have made a indication that
sudo ln -s /usr/local/BerkeleyDB.4.6/include/db.h /usr/include/db.h would have been useful for tools like openldap. Again to be continued..
configuration of the sources failed with:
checking for db.h... yes
checking for Berkeley DB major version... 1
checking for Berkeley DB minor version... 0
checking for Berkeley DB link (-ldb1)... no
checking for Berkeley DB link (-ldb-1)... no
checking for Berkeley DB link (default)... yes
checking for Berkeley DB version match... yes
checking for Berkeley DB thread support... no

the installed version of berkeleydb must be explicitly indicated by the cppflags:
env CPPFLAGS="-I/usr/local/BerkeleyDB.4.6/include" LDFLAGS="-L/usr/local/BerkeleyDB.4.6/lib" ./configure
openldap is reinstalled and is located in /usr/local/libexec
time to get jboss listen to ldap...

woensdag 19 september 2007

jsf Solutions for many2many: the dataTable

The datatable with rowselector.



Icefaces has extended the datatable with the possibility of a rowselector allowing remote method call of a listener method (Ajax). This feature wonderfully and intuitivily integrates with seam's datamodel and, even more important, seam's datamodelselection. The datamodel for a datamodelselection is a list with objects, which must have a isSelected method. No interface or super class is needed as this method is textual mentioned in the rowselector's value property. Check the roleItem code for a complete implementation.
Having learned a few things from jpa-ql and hibernate ql, and with the help of 2 colleagues I have been able to define an elegant query to populate a list with all the roles, and if present the actor for the subject having focus. In the same query I also construct the roleItem (See the RoleSubjectMgrBean.roleitms() code below), no list manipulation needed afterwards. I'm currently unaware whether the used syntax is allowed jpa-ql? Persisting the selection is a piece of cake (See the RoleSubjectMgrBean.rowSelection..) I only had to change the sessionbeans from session to conversation scope.

<ice:dataTable value="#{subjectRoleList}"
var="roleItem" rendered="${focusSubject.subjectid gt 0}">
<ice:column>
<ice:rowSelector selectionListener="#{roleSubjectMgr.rowSelection}" value="#{roleItem.selected}" multiple="true" selectedClass="selected"/>
<f:facet name="header"><h:outputLabel value="#{msgs['spuyt.subject.edit.role.list']}"/></f:facet>
<h:outputText value="#{roleItem.role.name}"/>
</ice:column>
</ice:dataTable>



Alas some drawbacks of this approach:


  1. The cursor doesn't change when hovering over the items.

  2. The subject in focus must be created before the datamodelselection can save its attached roles. This forces a conditional render of the datamodel

  3. By selecting a row the update is immediately executed on the database. Of course the cancel button gets a complete new meaning(less).

  4. Used query may not be jpa compliant



RoleSubjectMgrBean.java
001 package nl.jeroen.testdb.persist;
002 
003 import java.io.Serializable;
004 import ..;
028 import org.jboss.seam.log.Log;
029 
030 import com.icesoft.faces.component.ext.RowSelectorEvent;
031 
032 @Scope(ScopeType.CONVERSATION)
033 @Stateful
034 @Name("roleSubjectMgr")
035 public class RoleSubjectMgrBean implements Serializable, RoleSubjectMgr {
036     private static final long serialVersionUID = -9145745003284315431L;
037 
038     @Logger
039     Log logger;
040     
041     @In(required=false)
042     private Subject focusSubject;
043     
044     @In(required=true)
045     IApplicationSession sessionstore;
046     
047     @DataModel(value="subjectRoleList")
048     private List<RoleItem> subjectRoleList;
049     
050     @DataModelSelection(value="subjectRoleList")
051     @Out(required=false, value="focusSubjectRoleList")
052     private RoleItem focusSubjectRoleList;
053     
054     @PersistenceContext(type=PersistenceContextType.EXTENDED)
055     private EntityManager em;
056     
057     @Factory("subjectRoleList")
058     public void roleItems() {
059         //http://opensource.atlassian.com/projects/hibernate/browse/HHH-2772
060          subjectRoleList = em.createQuery("select new nl.jeroen.spuyt.util.RoleItem (r, a) 
        from Role r left join r.actors as a with a.subject.subjectid = :subject")
061             .setParameter("subject", focusSubject.getSubjectid()).getResultList();
062     }
063 
064     @Destroy @Remove
065     public void destroy() {
066     }
067     
068     public void rowSelection(RowSelectorEvent e) {
069         final String methodName = "rowSelection: ";
070         if (logger.isDebugEnabled()) {
071             logger.debug(LogUtil.getLogMessage(methodName, LogUtil.VERSION, "'"
072                     + focusSubjectRoleList + "'"));
073         }
074         if (focusSubjectRoleList.isSelected() ) {
075             // it was selected and now we're going to remove it.
076             focusSubject.getActors().remove(focusSubjectRoleList.getActor());
077             em.remove(focusSubjectRoleList.getActor());
078             focusSubjectRoleList.setActor(null);
079         } else {
080             // creating a new actor
081             Actor act = new Actor();
082             em.merge(focusSubject);
083             act.setPeriod(sessionstore.getFocusPeriod());
084             act.setRole(focusSubjectRoleList.getRole());
085             act.setSubject(focusSubject);
086             em.persist(act);
087             focusSubjectRoleList.setActor(act);
088         }
089     }
090     
091     public String persist() {
092         final String methodName = "persist: ";
093         if (logger.isTraceEnabled()) {
094             logger.trace(LogUtil.getLogMessage(methodName, LogUtil.VERSION,
095                     "starting '" + "'"));
096         }
097         try {
098             if (focusSubject.getSubjectid() == 0) {
099                 em.persist(focusSubject);
100                 return "selectSubject";
101             }
102             em.merge(focusSubject);
103         } catch (Exception e) {
104             logger.error("error occured:", e);
105             FacesContext.getCurrentInstance().addMessage("error on saving", new FacesMessage("error on saving"));
106         }
107         return "listSubject";
108     }
109 }


RoleItem.java
01 package nl.jeroen.spuyt.util;
02 
03 import nl.jeroen.testdb.persist.Actor;
04 import nl.jeroen.testdb.persist.Role;
05 
06 public class RoleItem {
07     Role role;
08     Actor actor;
09     
10     public RoleItem(Role r, Actor a) {
11         role = r;
12         actor = a;
13     }
14 
15     @Override
16     public String toString() {
17         return "name: '" + role.getName() + "' roleid " + role.getRoleid() + " actor " + actor;
18     }
19     
20     public boolean isSelected() {
21         return (actor != null);
22     }
23     
24     public void setSelected(boolean selected) {
25     }
26 
27     public Role getRole() {
28         return role;
29     }
30 
31     public void setRole(Role role) {
32         this.role = role;
33     }
34 
35     public Actor getActor() {
36         return actor;
37     }
38 
39     public void setActor(Actor actor) {
40         this.actor = actor;
41     }
42     
43 }


zondag 22 april 2007

icefaces 163

Just downloaded the 163 release from icesoft appeared they have fixed the bug I blogged about before. I tried to use it in my project but it doesnot start yet.
First I had to copy over 2 jars: Class not found: FileUploadBase$FileSizeLimitExceededException (commons fileupload), and facelets-icefaces not that exciting, jboss starts and ear deploys but I dont see my datatable now. Query gets excecuted. But no field generation, nada nothing.
First I'm going to see whether its possible to switch to jsf1.2 (Apparant changing the myfaces impl jars to the jsf ref ones).

dinsdag 17 april 2007

implementing many2many

I'm currently trying to implement a many2many relationship. Using jsf's selectMany thingy. Apparantly jboss seam does have something similar integrated in seam, now I've to use selectitems, converters and what's more. I tried the seam implementation a while ago, but I couldnt get it to work it also had a beta in the name, which is discouraging.

As the myfaces/icefaces combination also has shown some weird behavior I decided to download both and add them as projects in eclipse, so I can do some debugging, and add logging. A feature with both products seriously lack.
Myfaces is build with maven :
D:\projects\seamice\myfaces\core> d:\programs\maven-2.0.4\bin\mvn 
produces the api and impl files, which can be copied:
 copy /Y  impl\target\myfaces-impl-1.1.6-SNAPSHOT.jar d:\programs\jboss-4.0.5.GA\server\default\deploy\jbossweb-tomcat55.sar\jsf-libs\myfaces-impl.jar 

(and repeat cmd above for the api jars, donot copy the source jars).

The first obstacle I encountered was the output.
I did do something like:
SelectItem item = new SelectItem();
item.setLabel(role.getName());
item.setValue(role.getValue());
But the output in the html both value and label as the label.

IceFaces:
codesnippet MenuRenderer:

if (logger.isTraceEnabled()) {
logger.trace(LogUtil.getLogMsg(methodName, LogUtil.VERSION
,"start to render option for '" + uiComponent.getId() + "' and item label '" + selectItem.getLabel() + "' and itemvalue '" + selectItem.getValue() + "'"));
}
DOMContext domContext =
DOMContext.attachDOMContext(facesContext, uiComponent);

Element select = (Element) domContext.getRootNode();
Element option = domContext.createElement("option");

if (optionGroup == null) {
select.appendChild(option);
} else {
optionGroup.appendChild(option);
}

String valueString = formatComponentValue(facesContext, uiComponent,
selectItem.getValue());
if (logger.isDebugEnabled()) {
logger.debug(LogUtil.getLogMsg(methodName, LogUtil.VERSION
, "created option gets value assigned of '" + valueString + "'"));
}

And the logging output:

15:16:05,593 TRACE [com.icesoft.faces.renderkit.dom_html_basic.MenuRenderer] renderOption[0.1]:start to render option for '_id61' and item label 'Spuyt' and itemvalue '1'
15:16:05,656 TRACE [javax.faces.component.UISelectMany] getValueBinding[0.1]:start with 'converter'
15:16:05,671 INFO [nl.jeroen.testdb.persist.SubjectMgrBean] getting as string for '1' class java.lang.Integer'
15:16:05,671 INFO [nl.jeroen.testdb.persist.SubjectMgrBean] getting as string for '1' class java.lang.Integer'
15:16:05,671 DEBUG [nl.jeroen.testdb.persist.SubjectMgrBean] [getRoleValues: ]0.1: starting ''
15:16:05,687 DEBUG [com.icesoft.faces.renderkit.dom_html_basic.MenuRenderer] renderOption[0.1]:created option gets value assigned of 'Spuyt'
In between something is going wrong and apparantly its the converter.getAsString method is being called, and this nicely retrieves the role with the passed argument as id, and returns the name.
But this is exactly why I switched back to Integers instead of the Roles because the conversion back (getAsObject) is not working as expected.
Because after submitting the form, I'd expect the getAsObject method to be called before the HTMLSelectManyListbox(UISelectMany).validateValue() (part of myfaces) but that's not happening.
validateValue's signature is:

validateValue(FacesContext context, Object convertedValues)

but my own logging states:

validateValue[0.1]:validate Value '[2, 6]'

convertedValues would expect that the values have been converter.getAsObject(..) but alas..
iceface's blocking servlet is doing in rendercycle, lifecycle.execute();


UISelectMany does contain a getConvertedValue method which delegates the conversion of the submitted values to a renderer (MenuRender in our case). This menurenderer is not calling the converter.getAsObject so there's the error!

Why is eclipse code formatter putting all the operands on the end of the line? I would prefer it to put at the start of the line, in case of long lines you don't have to scroll right. (I use the term operands here for characters like + . , etc)

Icefaces seam and all

Hopefully an effort which will last to monitor my progress on my journey into jboss seam, icefaces and other relevant technologies. In the far past I used to be the treasurer of my volleybalclub, and I made a nice webapplication for maintaining all my expenses, credits debets etc. This application was made in Silverstream my employer at that time, but Silverstream went out of business or novell took over or god knows what and I havent been able to maintain the application or even migrate the application.
Of course my suceessor used Excel again and nothing wrong with Excel but I still have the feeling that there might be some business in a small treasure like application for small / medium sized clubs or institutes. I'm not really hindred by a bookkeeping or economic background, so that is not an obstacle.
Since 4 or 5 years I've been carrying the idea of reimplementing the application using the various opensource java techniques available at time. EJB 1.1, 2, struts, jsp, jsf, tapestry jsf etc. All without much result, I just haven't been able to master the technologies without proper guidance or education in my own spare time. Looking at the ejb3 comments its probably not really a shame, but It felt like it and finally I dare to speak out openly.
Lately I discovered seam and jboss and I have the feeling that this combination with jsf (icefaces) may work out. Hopefully I'm capable of keeping this blog up to date so people may benifit from it and otherwise it might be a worthwile resource for me to look back.