Java NAPI: Enable / Disable Recycling of C Handles

Initialize Java NAPI

com.ibm.domino.napi.c.C.initLibrary( "" );

Disable Recycling

com.ibm.domino.napi.c.BackendBridge.setNoRecycle( session, session, true );

Enable Recycling

com.ibm.domino.napi.c.BackendBridge.setNoRecycle( session, session, false );

To use these methods in an agent, you have to import some Jars first.

Veröffentlicht unter Java | Verschlagwortet mit | Hinterlasse einen Kommentar

XPages & Domino JNA

Karsten Lehmann has published a very promising project named „Domino JNA„, which allows access to the underlying IBM Domino/Notes C API from Java.

If you want to use the project in a XPages, you have to add some Java permissions to the java.pol file on your server:

grant {
    permission java.util.PropertyPermission "jnidispatch.path", "write";
    permission java.util.PropertyPermission "jna.loaded", "write";
}

Additionally, you have to import the following JARS from „domino-jna\target\lib“ (after a successfull Maven build) to a directory on the server (jvm/lib/ext) or import it into an NSF:

  • commons-collections4-4.0.jar
  • jna-4.2.2.jar
  • joda-time-2.9.2.jar
Veröffentlicht unter Java, Security, Server, XPages | 1 Kommentar

Vaadin In XPages: A UIComponent for embedding Vaadin applications

I have created an UIComponent to embed Vaadin applications into XPages. It allows to run both technologies on the same site by adding it to your XPage:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view
    xmlns:xp="http://www.ibm.com/xsp/core"
    xmlns:vaadin="http://vaadin.com/xsp/control"
    createForm="false">
    

    <!-- XPages Application -->
    <xp:form>
        <xp:div id="refreshMe">
            <h1>XPage</h1>
            <xp:label
                value="#{javascript:java.lang.System.nanoTime()}"
                id="label1">
            </xp:label>
        </xp:div>
        <xp:button
            value="refresh"
            id="button1">
            <xp:eventHandler
                event="onclick"
                submit="true"
                refreshMode="partial"
                refreshId="refreshMe">
            </xp:eventHandler>
        </xp:button>
    </xp:form>
    
    <!--  VAADIN Application -->
    <vaadin:Vaadin
        id="Vaadin1"
        url = "/vaadin/"
        divId="addressbook"
        version="7.3.8"
        forceResize="true" />
        
</xp:view>

This little example shows the XPage above including the the Adressbook application:

2016-05-03 12_31_17-VaadinInXPages

The Vaadin application is reachable at „http://localhost/vaadin/“ (hosted by Domino), that’s why the property url is set to „/vaadin/„. The property divId contains the name of the application which is used as id in the DOM tree.

It is required that the VaadinComponent is not inside a xp:form element. If it detects a surrounding form, a runtime exception is thrown. That’s why you have to set createForm to false and add your own xp:form to your application, as shown in the example.

2016-05-03 12_50_11-Runtime Error

If the parameter forceResize is set to true, a CSS style sheet is added to the XPage which resizes the height of html and the body node to 100%. Otherwise the Vaadin application will not be displayed correctly.

2016-05-03 12_54_35-view-source_localhost_VaadinInXPages.nsf_index.xsp

Resource Aggregation must be disabled, otherwise it won’t work.

The sources can be found at https://github.com/hasselbach/VaadinInXPages

Veröffentlicht unter Vaadin, XPages | Verschlagwortet mit , | 2 Kommentare

EntwicklerCamp 2016: XPages erweitern und ausbauen

Die PDF Version meiner Entwickler Camp 2016 Session „XPages erweitern und ausbauen“ gibt es hier: ec2016-Votrag-XPagesErweiternUndAusbauen.pdf

Die verwendeten Sources finden sich in diesem Repository auf GitHub: ec2016-xpages-erweitern

Bei Fragen/Problemen einfach eine kurze Info an mich.

Veröffentlicht unter EC 2016, XPages | Verschlagwortet mit , | Hinterlasse einen Kommentar

EntwicklerCamp 2016: Ein Leben ohne Notes Client

Hier gibt es die PowerPoint Präsentation von meiner Entwickler Camp 2016 Session „Ein Leben ohne Notes Client“: ec2016-Votrag-LebenOhneNotesClient.pptx

Die kompletten Sources finden sich in diesem Repository auf GitHub: ec2016-ein-leben-ohne-notesclient

Bei Fragen/Problemen einfach eine kurze Info an mich.

UPDATE: Hier die PDF Version.

Veröffentlicht unter EC 2016, Java, JavaFX | Verschlagwortet mit , , | Hinterlasse einen Kommentar

Kurze Werbeunterbrechung

Probleme bei der XPages-Entwicklung? Schulung gefällig?
Fehlt die eine oder andere Komponente? Oder wird ein neuer Renderer benötigt, der zur Abwechslung mal den HTML Code generiert, den man gerne hätte?

Ich biete gerne meine Unterstützung an.
Einfach mal Kontakt aufnehmen. Gern auch per Mail: contact <at> hasselba.ch

Veröffentlicht unter Allgemein | Hinterlasse einen Kommentar

How To Crash a Domino Server in 500ms

How To Crash a Domino Server in 500ms

1. Create a Java agent and do something in your finally block (or in a ThreadDeath exception handling) which runs longer than 500ms

import lotus.domino.AgentBase;

public class JavaAgent extends AgentBase {

    public void NotesMain() {
        try {
            int i = 0;
            while (i < 1000) {
                i++;
                System.out.println("Round " + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {}
            }
        } finally {
            try {
                Thread.sleep(1000);
            } catch (Exception e) {}
        }
    }
}

2. Run the agent on the server

2016-02-20 11_31_17-SH Domain - Dev01_Hasselba_CH - IBM Domino Administrator1

3. Quit the Agent Manager

2016-02-20 11_31_17-SH Domain - Dev01_Hasselba_CH - IBM Domino Administrator2

4. And then restart it

2016-02-20 11_31_17-SH Domain - Dev01_Hasselba_CH - IBM Domino Administrator3

5. Enjoy the silence

2016-02-20 11_31_17-SH Domain - Dev01_Hasselba_CH - IBM Domino Administrator4

Fun fact: This works well in a IBM Notes Client too! Just start the agent and cancel it a few times (<CTRL> + <BREAK>).

Veröffentlicht unter Agenten, Bug, Java, Server | Verschlagwortet mit , , , | 2 Kommentare

Vaadin IBM Challenge

Since two weeks the Vaadin IBM challenge is over. While I was only able to do the bare minimum, I really enjoyed the different tasks (see here for list of steps).

Congrats to the winners! And thanks to the Vaading Team & IBM for this exciting experience.

Veröffentlicht unter Vaadin | 4 Kommentare

Things I never blogged about: XPages & Google’s EventBus

This is another topic I wanted to blog about for a long time: The use of Google’s EventBus in XPages applications. EventBus is a replacement for the Java in-process event distribution. It makes life a lot easier.

My first plan was to add the guava.jar into an OSGi plugin because of security reasons (otherwise you have to use the „grant{ permission java.security.AllPermission;}„) but I never had the time. That’s why I created a simple example which uses the jar in the lib/ext folder instead.

To use the EventBus in an application, you first have to define an event. This simple example has a message only, but you can add any properties you want.

package ch.hasselba.xpages;

public class FrontendEvent {

    private final String message;

    public FrontendEvent(final String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

}

Then we need a subscriber. For this we have to add the annotation @Subscribe to a method of a managed bean which should handle an event. The class type of the parameter tells the EventBus what kind of event our method should handle.

This is a managed bean which stores the last message sent over the EventBus:

package ch.hasselba.xpages;

import com.google.common.eventbus.Subscribe;

public class EventSubscriber {

    private String message;

    @Subscribe
    public void handleEvent(FrontendEvent event) {
        this.message = event.getMessage();
    }

    public void getMessage(String msg) {
        this.message = msg;
    }

    public String getMessage() {
        return this.message;
    }
}

Then we have to create a managed bean which has an instance of EventBus, the FrontendEventBus. The bus has a managed property subscribers. As soon the bean is instantiated, the managed property is called and the list of objects is registered to the EventBus instance.

package ch.hasselba.xpages;

import java.io.Serializable;
import java.util.ArrayList;

import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.SubscriberExceptionContext;
import com.google.common.eventbus.SubscriberExceptionHandler;

@SuppressWarnings("serial")
public class FrontendEventBus implements SubscriberExceptionHandler,
        Serializable {

    final EventBus eventBus = new EventBus();
    ArrayList<Object> subscribers;

    /**
     * registers all subscribing managed beans from faces-config.xml
     * 
     * @param subscribers
     *            ArrayList with references to managed beans
     */
    public void setSubscribers(ArrayList<Object> subscribers) {
        this.subscribers = subscribers;
        for (Object subscriber : subscribers) {
            register(subscriber);
        }
    }

    public void post(final Object event) {
        eventBus.post(event);
    }

    public void register(final Object object) {
        eventBus.register(object);
    }

    public void unregister(final Object object) {
        eventBus.unregister(object);
    }

    public final void handleException(Throwable exception,
            SubscriberExceptionContext context) {
        exception.printStackTrace();

    }

}

There is only one problem: If a bean is in a lower scope, the initialization will fail. In this case we have to do the opposite to attach a subscriber to the bus. Instead of telling the bus which subscriber we want to register, we are telling the subscriber which bus to attach to.

package ch.hasselba.xpages;

public class EventSubscriberRequestScope extends EventSubscriber {

    /**
     * registers the current instance to the event bus
     * 
     * @param eventBus
     *            the frontend event bus
     */
    public void setEventBus(FrontendEventBus eventBus) {
        eventBus.register(this);
    }

}

As soon the bean is instantiated, the managed property will have an instance of our FrontendEventBus and the bean can register itself.

The faces-config.xml looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<faces-config>

    <managed-bean>
        <managed-bean-name>frontendEventBus</managed-bean-name>
        <managed-bean-class>ch.hasselba.xpages.FrontendEventBus</managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
        <managed-property>
            <property-name>subscribers</property-name>
            <list-entries>
                <value-class>java.lang.Object</value-class>
                <value>#{eventSubscriber}</value>
            </list-entries>
        </managed-property>
    </managed-bean>
    
    
    <managed-bean>
        <managed-bean-name>eventSubscriber</managed-bean-name>
        <managed-bean-class>ch.hasselba.xpages.EventSubscriber</managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
    </managed-bean>
    
    
    <managed-bean>
        <managed-bean-name>eventSubscriberRequestScope</managed-bean-name>
        <managed-bean-class>ch.hasselba.xpages.EventSubscriberRequestScope</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
        <managed-property>
            <property-name>eventBus</property-name>
            <value>#{frontendEventBus}</value>
        </managed-property>
    </managed-bean>
    
</faces-config>

The first subscribing bean is in the same scope as the FrontendEventBus, but the second one is a request scoped bean.

Now it’s time to send an event. This can be realized by creating a new instance of our FrontendEvent we have created earlier and posting it to the bus.

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">

    <xp:button
        id="button1" value="Click me">
        
        <xp:eventHandler
            event="onclick"
            submit="true"
            refreshMode="complete">
            <xp:this.action>
                <![CDATA[#{javascript:importPackage( ch.hasselba.xpages );
                    var msg = "Timestamp: " + java.lang.System.currentTimeMillis();
                    var se = new ch.hasselba.xpages.FrontendEvent( msg );
                    frontendEventBus.post( se );
                }]]>
            </xp:this.action>
        </xp:eventHandler>
    
    </xp:button>
    
    <br />
    <br />
    
    <xp:label
        value="#{eventSubscriber.message}"
        id="labelSubscriberMessage">
    </xp:label>
    
    <br />
    
    <xp:label
        value="#{eventSubscriberRequestScope.message}"
        id="labelSubscriberRequestScope">
    </xp:label>
    
</xp:view>

As soon the button is clicked, both beans are receiving the event and updating their message.

2015-12-01 14_04_04-Mozilla Firefox

Hope someone finds it usefull.

Veröffentlicht unter Java, JSF, XPages | Hinterlasse einen Kommentar

Things I never blogged about: The XPagesExecutor Service

The XPages engine has its own executor service to run jobs concurrently in another thread: the XPagesExecutor service. Under the hood the service uses a ThreadPoolExecutor for executing tasks, so it allows to use Runnables or Callables/Futures for asynchronous computation. For fun, you can even run a server instance, the started threads can run as long as you want (e.g. they are not bound to the XPages lifecycle).

Here is a small XPage with a button to start a Runnable via the Executor:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
    
    <xp:button
        value="run the job"
        id="buttonDoIt">
        <xp:eventHandler
            event="onclick"
            submit="true"
            refreshMode="complete">
            <xp:this.action>
                <![CDATA[#{javascript:
                importPackage(ch.hasselba.xpages);
                new ch.hasselba.xpages.DemoExecutor().doIt();}]]>
            </xp:this.action>
        </xp:eventHandler>
    </xp:button>
    
</xp:view>

To use the Service, you have to aquire it first, then you can execute a Runnable like in this code snippet:

package ch.hasselba.xpages;

import java.util.concurrent.ExecutorService;

import lotus.domino.NotesException;
import lotus.domino.Session;

import com.ibm.domino.xsp.module.nsf.NSFComponentModule;
import com.ibm.domino.xsp.module.nsf.NotesContext;
import com.ibm.domino.xsp.module.nsf.SessionCloner;
import com.ibm.xsp.application.XPagesExecutor;

public class DemoExecutor {
    private final NSFComponentModule module;
    private final SessionCloner sessionCloner = SessionCloner
            .getSessionCloner();

    public DemoExecutor() {
        // get the current NSFComponentModule
        this.module = NotesContext.getCurrent().getModule();
    }

    public void doIt() {
        // aquire the Executor
        ExecutorService exService = XPagesExecutor.acquire();
        
        // run the Runnable
        exService.execute(new DemoRunnable(this.module));
    }

    class DemoRunnable implements Runnable {
        private final NSFComponentModule module;

        public DemoRunnable(NSFComponentModule module) {
            this.module = module;
        }

        public void run() {
            try {

                // init the NotesThread
                NotesContext context = new NotesContext(this.module);
                NotesContext.initThread(context);

                // now do the job...
                System.out.println("Starting the job...");
                Session session = null;
                try {
                    // grab the session
                    session = sessionCloner.getSession();
                    System.out.println("Running as "
                            + session.getEffectiveUserName());
                    Thread.sleep(10000);
                } catch (NotesException e) {
                    e.printStackTrace();
                } finally {
                    DominoUtils.recycle( session );
                }
                System.out.println("Done!");

            } catch (InterruptedException ie) {
                // handle interruption here
            } finally {
                // kill the Notes thread
                NotesContext.termThread();
            }
        }

    }

}

2015-11-29 08_54_13-SH Domain - Dev01_Hasselba_CH - IBM Domino Administrator

Callables must be submitted instead:

   public long doItWithCallable() {

        ExecutorService exService = XPagesExecutor.acquire();
        Future<Long> result = exService.submit(new MyCallable(this.module));
        long returnValue = (-1);

        try {
            returnValue = result.get();
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        } catch (ExecutionException ee) {
            ee.printStackTrace();
        }

        return returnValue;
    }

    class DemoCallable implements Callable {
        private final NSFComponentModule module;

        public DemoCallable(NSFComponentModule module) {
            this.module = module;
        }

        public Long call() throws Exception {
            try {

                // init the NotesThread
                NotesContext context = new NotesContext(this.module);
                NotesContext.initThread(context);

                // now do the job...
                System.out.println("Starting the job...");
                Session session = null;
                try {
                    // grab the session
                    session = sessionCloner.getSession();
                    System.out.println("Running as "
                            + session.getEffectiveUserName());
                    Thread.sleep(10000);
                } catch (NotesException e) {
                    e.printStackTrace();
                } finally {
                    DominoUtils.recycle( session );
                }
                System.out.println("Done!");

            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                // kill the Notes thread
                NotesContext.termThread();
            }

            return System.currentTimeMillis();
        }

    }

Hope someone finds it usefull.

Veröffentlicht unter Java, XPages | 2 Kommentare