bookmark_borderquindip: debugging java in xPages made simple (four steps)

for some of you this might be the almost perfect XMas gift from me.

I finally figured how to debug Java code in an xPage application, and it’s DEAD SIMPLE…

if only more people would blog about it…

so here is how:

1. Create a debug configuration. The debug button might not always be visible, you will see it definetely by switching to the Java perspective.

2. add those 2 lines to your notes.ini and restart your notes client/designer
JavaEnableDebug=1
JavaDebugOptions=transport=dt_socket,server=y,suspend=n,address=8000
3. set any break point
4. do anything on an xPage which goes to Java, say using a Managed Bean or call a method from a normal Java class and voilà the debugger activates and you can check your code..
Most probably the first attempt will result not result in actually seeing code… you might get this result:
don’t desperate, click the button and then add your project and you will see your code… 
I wonder why IBM does not promote this VERY VERY VERY publicly… you have to again.. by accident stumble accross a video from Niklas Heidloff (kudos to him) 
this will save me soooooooooooooooooooooooooooooooooooooooooooooooo many headaches!!!

bookmark_borderquindip: prevent SameTime windows popping to the front

do you use SameTime? we use it a lot!
are you annoyed when someone sends you a message and the window pops to the front while you are typing something somewhere? I am!

here is the solution:

the setting “Bring chat window to front” is VERY hidden! You have to select the one-on-one chat notification to actually see that property!

bookmark_borderquindip: make accessing events/properties faster

Are you annoyed having to click x-times to get to your properties/events?

I am…

but how about this:

Detach the properties and events views and place them on a separate monitor so that you always have them available. I use an external screen and have the properties/events views detached on my internal LCD.

right click header of the view in designer and select “Detached”

This way I don’t bother resizing the panel on the bottom every 10 seconds. I click a field or any other element and then I turn my head to look at my secondary screen and have immediate access to all my properties/events I need…

this would be even cooler if it would work with <alt><tab> but it doesn’t! (->IBM: do you listen/read?)

bookmark_borderquindip: more mysteries about scoped variables solved

I don’t know about you.. I was for quite some time not quite getting the hang on “requestScope” and “viewScope” variables.

I did understand the “sessionScope” and the “applicationScope” variables.

after a few weeks of playing around with xPages, getting quite deep into JSF  framework etc, I had today finally (maybe only to me) a stupid revelation:

why a requestScope and a viewScope variable is called this way, and thus understand properly how it works

requestScope
Say you have a webpage open and you now click a button (ie. to save a document). The page (or parts of it) are sent back to the server (mostly via post, sometimes via a get HTTP request). When you in this button now set a requestScope variable you can actually use this value in the next page to be opened. I personally will use this to detect which view is most likely to be opened after a document has been submitted.

There is a little tweek to be made to get this working properly, see my other post.

viewScope
the viewScope is only valid as long as you stay on the same page! and if you know that an xPage is essentially (in JSF terms) a “view” you now also know the reason why it’s called a “viewScope” variable.

Use case why I would use  viewScope variable I don’t really have, but you could use it example to track how many times a user has refreshed the current webpage, say to switch between tabs etc. This could help you to track down bottlenecks in your layout.

bookmark_borderyour turn!

What are your most urgent issues regarding development with XPages?

let me know and write a comment.

Why I would like to know?

Well in the past few weeks when I tried to get the XPages framework for our company up and running, I spent countless hours doing research on the internet. And mostly I either didn’t find the information I was looking for at all, or it took me too long and I had to “syndicate” bits and pieces from various sources into a model which would work for me…

just take the example of “scoped variables”. In every XPage session/training I attended so far they tell you about the application/session/view/request scope variables.

No-one can really tell you exactly what the difference between view and request scope variable is.

and No-one can actually tell you how you get the request scope variables to work! Most XPage developers think they don’t work at all.

The reason for this is: we (yes, I include myself as well into that group of people) lack a good amount of necessary background knowledge how HTTP and JSF really work.

As soon as you get the chance to talk to certain people who know more about those topics, you start to realize things and suddenly the puzzle pieces fit together and form a quite nice image.

yours

Michael

bookmark_borderindip: inject JS into xPage dynamically

wow…

so… as you can see.. I was struggling lately a lot with how I could my validation work the way I want it…

I would like to setup some configuration documents where I can define certain criteria upon which my documents (ie. xPages) are validated….

so the simple (required/threshold/regex pattern) ones I got (at least as a prototype) working…

what was still missing was a way to inject “logic” into my validation via setup document..

With LotusScript you could simply use “Evaluate” and the code provided in the setup document would be “evaluated” (ie executed)..

But how the hell can you achieve something similar in xPages? Well working with JavaScript it would be a breeze… as there exists also an “eval” statement.

But as I was/am trying to get our framework working based as much as I can on Java language some other mechanism should be applied.

As I cannot just simply inject some code into a running (already compiled Java class) this would not be so easy. A colleague mentioned 3 methods.
One method I forgot, the other were: use an own class loader and load a full class on the fly. Might work, but I am 100% sure the Notes JVM security model would cough on it.
The third was to use EL expressions with an ExpressionFactory. Would have been a way to go…

But lazy as I was I was trying to figure out a way how I could inject JavaScript into running Java code.

and guess what.. I was lucky and figured it out:

here’s the code:

FacesContext facesContext = FacesContext.getCurrentInstance();
PageExpressionEvaluator eval = new ExpressionEvaluatorImpl(facesContext);

MethodBinding method = eval.createMethodBinding(
facesContext.getViewRoot(),
“#{javascript:var c = getComponent(“field1”);document1.replaceItemValue(“test”,c.getValue()); document1.save()}”,
null, null, null);

// other examples of JavaScript code to “experiment”
// “#{javascript:print(“hello world”)}”
// “#{javascript:return true}”

method.invoke(facesContext, null);

As you can see the interesting stuff is going on in the second parameter of the method createMethodBinding. There you can inject JavaScript code. Just enter your code into a button and then copy the relevant piece out of your xPage XML source code! In our framework this code will be read from the configuration document!

I admit.. the solution is “semi-optimal” cause I wanted to get rid of JavaScript as much as I can. But then hey: I don’t use those “formulas” very often, and for those rare cases I think I can accept the performance dip.

dip? indip? INDispensabletIP!

a side-dip: any ideas how I got the idea of how to get this working?

check this out:

in the package explorer view under Localxsp you will find the source code for all your xPages and custom controls! Just create a simple xPage with a button, add some JavaScript to the button and you basically get the code I posted above!

bookmark_borderindispensable tip: how to bind domino form to a xPage

if you want to keep your design straightforward use as Form in the data binding section the same name as the xPage name:

this will allow you to open a document created with this xPage without knowing it’s corresponding xPage with the following URL command:

/path/to/your/db.nsf/$$OpenDominoDocument.xsp?documentId=UNIVERSALID

If you do it this way you do not even need to bind a notes form to the corresponding xPage:


Drawbacks?

there is… you cannot use the Data view to drag&drop the fields from the Domino form onto the xPage:

there are no fields defined the data view could provide you with.
and you have to set all the data binding yourself: add the fieldName of the field where you want to store the value of this “component” manually (just type it in!`)

bookmark_borderfinal solution preventing validators to kick-in when not required

remember? it was first days, then hours, okay, today hours as well.. but I think with some help of you guys out there blogging also I found the final solution, and the times do get better and better, as I get more and more knowledge about the whole thing.

summary:

  • use the PhaseListener to catch the phase: PROCESS_VALIDATIONS
  • add some code to the beforePhase event (to disable the validators for all but the required events)
  • add some code to the afterPhase event (to enable the validators again)
  • add a recursive method which will enable/disable (ie toggle) all available validators
  • add event parameters to your buttons where you DO WANT TO trigger the validators

PhaseListener updates:

  • add this code in the beforePhase method, it will disable the validators if no event parameters (name=requireValidation, value=true) are present

FacesContext facesContext = event.getFacesContext();
try {
    // handle validators
    if (event.getPhaseId().equals(PhaseId.PROCESS_VALIDATIONS)) {
// add validators if required
// i use:    
//CustomValidator v = new CustomValidator();
//v.handleValidators();

        // if not submitted via save button disable validators
        // get eventHandlerClientId
        String eventHandlerClientId = (String) facesContext
                .getExternalContext().getRequestParameterMap().get(
                        “$$xspsubmitid”);
        // extract eventHandlerId
        String eventHandlerId = eventHandlerClientId.substring(
                eventHandlerClientId.lastIndexOf(“:”) + 1,
                eventHandlerClientId.length());
        // get eventHandler “component”
        UIEventHandler eventHandler = (UIEventHandler) Util
                .findComponent(facesContext.getViewRoot(),
                        eventHandlerId);

        // find the parameters set via Edit Event parameters on the
        // Events page
        boolean skipValidation = true;
        List<Parameter> parameters = eventHandler.getParameters();
        if (null != parameters) {
            Iterator<Parameter> iterator = parameters.iterator();

            while (iterator.hasNext()) {
                Parameter par = iterator.next();
                if (par.getName().equals(“requireValidation”)
                        && par.getValue().equals(“true”)) {
                    skipValidation = false;
                    break;
                }
            }
        }
        if (skipValidation) {
            toggleValidators(facesContext.getViewRoot(), true);
        }

    }
} catch (Exception e) {
    // default disable validations for all other events which are not
    // “requireValidation=true” and which might throw an error while trying to get their event handler
    toggleValidators(facesContext.getViewRoot(), true);
}

  • add this code to the afterPhase, it will enable the validators again:

if (event.getPhaseId().equals(PhaseId.PROCESS_VALIDATIONS)) {
    FacesContext facesContext = event.getFacesContext();
    toggleValidators(facesContext.getViewRoot(), false);
}

  • add this method, it will recursively find all components where validators might be existing and enables/disables them. This method is most likely candidate for speed improvements: You could use as parent component the actual tab (for tabbed panels) being displayed, but then you would have to track which one is selected, I prefer to just run it on the whole tree to make it simple for now
private void toggleValidators(UIComponent parent, boolean toggle) {

    List<UIComponent> children = parent.getChildren();
    Iterator<UIComponent> iterator = children.iterator();
    while (iterator.hasNext()) {
        UIComponent child = iterator.next();
        if (child instanceof javax.faces.component.UIInput) {
            if (child instanceof com.ibm.xsp.component.UIInputEx) {
                UIInputEx input = (UIInputEx) child;
                input.setDisableValidators(toggle);
                if (0 < child.getChildCount()) {
                    toggleValidators(child, toggle);
                }
            } else if (child instanceof com.ibm.xsp.component.UISelectOneEx) {
                // radio/checkbox/combobox etc.
                UISelectOneEx input = (UISelectOneEx) child;
                input.setDisableValidators(toggle);
                if (0 < child.getChildCount()) {
                    toggleValidators(child, toggle);
                }
            }
        } else {
            if (0 < child.getChildCount()) {
                toggleValidators(child, toggle);
            }
        }
    }
}

  • add an event parameter to all your buttons where you do want to trigger the validation

et voilà.. you have a nice working form where validators are only triggered when really required (ie. upon save)!
no more stupid validations kicking-in when switching tabs, clicking buttons, refreshing via combo boxes panels etc…
as for the “Save as draft” button: I would recommend that you add a field on the form “flagIsDraft” so that you can take care of not postprocessing such documents
Kudos go to Tommy Valand and weihang chen, their “blogs” helped me get my way through!