Posts Tagged: ‘Java’

High Performance REST Applications (3) – Importing the Starter Project

24. April 2017 Posted by Sven Hasselbach

Now you can import the projects required from Git.

First, go to „File > Import…

Import Project

Then select „Projects from Git“

Projects from Git

and „Clone URI“ to clone an existing repository:

Clone existing respository

To get the URI, you have to open https://github.com/hasselbach/ and select the repository „ch.hasselba.concurrent„. Click the „Clone or download„-Button and copy the URI from the opening box:

Get the repository URI

Paste the URI into the location in Eclipse

Add the URI to Eclipse

In the next dialog, you can choose the branch to import. In this case, only „master“ exists

Select the branch to import

Now you have to choose a local destination where the cloned repository will be stored

Select the local destination

Select „Import existing Eclipse projects„…

Import existing projects

… and select all projects of the repository:

Select all projects

With „Finish„, the sources are downloaded. In the „Project Explorer„, you can see the three imported projects. And you can see the original repository name and the current branch you are working on:

Repository & Branch

The JRE used for the project can be seen if you expand one of the projects. „Sometimes“ this changes magically, and the build will fail – that is one of the first things you have to check if you have errors in a OSGi project.

JRE / Target used for this project

Now, do the same for the „domino-rest-servlet“ repository. But instead importing the „master“ branch, select the „highperformance“ branch only.

Import HighPerformance Branch

That’s it. In the next post, we have take a look in what you have downloaded.

High Performance REST Applications (2) – Dev Environment

23. April 2017 Posted by Sven Hasselbach

Before you can start developing a Servlet as an OSGi Plugins, you must set up a development environment first. To do this, download Eclipse IDE (Eclipse IDE for Java EE Developers) and XPages SDK from OpenNTF (The XPages SDK is a helper to create the JRE environment and the Target Platform). For development it is the best to have a (local) development server, because during development you might want to restart and/or modify it, and debugging is a lot easier if have control over the whole server.

After unpacking Eclipse and the XPages SDK, you have to install it and set up the JRE and the Target Platform. Go to „Help > Install New Software“. With „Add…“, you can add the UpdateSite of the XPages SDK to Eclipse:

Install New Software

Add Update Site

Click on „Local…“, and choose the folder „org.openntf.xsp.sdk.updatesite“ from the unpacked archive. Then give it a name for identification. You can choose whatever you want.

Choose the XPages SDK UpdateSite

Now, choose the plugin, click „OK“, accept the license, allow the installation from unsigned content and restart Eclipse after installation is complete.

Install the Plugin

Next step ist to configure the JRE: Go to „Help > Preferences“, „XPages SDK“, and choose the pathes were your Domino Server is installed. Also choose „Automatically create JRE for Domino“:

Then apply it.

If you have FP8 installed, you don’t need the next step: Change the Complier compliance level to 1.6. Again, apply the setting and allow a full rebuild of the Workspace.

Change the compliance level

Switch the default JRE to the newly created XPages Domino JRE:

Now you have to add the target platform: Enter „target“ in the search field, select the „Target Platform“, and click on „Add“. Choose the „Domino Install Target“, create it and choose it as active platform.

Target Definition: „Domino Install Target“

OK, that’s it. You have a working IDE and you are ready to import the starter project from GitHub.

High Performance REST Applications (1) – Intro

21. April 2017 Posted by Sven Hasselbach

This is a new serie about developing high performance REST applications on top of Domino. It will contain my presentations from SNoUG and EntwicklerCamp this year and describes all required steps to develop, build and deploy these servlets on a basic level.

The code used in this serie is already available at GitHub:

(The high performance part is in a branch of my example Domino REST Servlet described earlier in this blog.)

The serie will start with setting up the development environment, explaining OSGi plugin basics and will then go over how to implement the REST API. Some details about concurrency developments and their problems will also be included. Hopefully it is easy to understand.

Don’t hold back to ask a question in the comments or to contact me directly. I have kicked out the buggy comment plugin last month, so you should be able to post them even when I have updated my wordpress installation.

Relax and enjoy the upcoming posts.

Domino & Java 1.8: Thank you, IBM!

14. März 2017 Posted by Sven Hasselbach

For years it was a lot of pain when developing for the Domino platform using Java 1.6 only. But now, Java 1.8 is available, and this allows to use the latest versions for a lot of libraries and development tools.

After installing FP8 to the Client, Eclipse allowes to use the Domino JRE in a JavaSE-1.8 environment:

This gives access to the latest M2Eclipse plugin (1.7.0). The old version problem when running with JRE 1.6…

… is solved:

Eclipse Updates? No problem, just do it!

Latest Java features like switch statement with Strings? Here we go:

String token = "FOO";
switch(token) {
    case "FOO": return (T) Foo.class;
    case "BAR": return (T) Bar.class;
}

Third party libraries like Jackson 2.8.0? Works like a charm!

Thank you, IBM!

IBM Notes und Domino Feature Pack 8 – Sie haben es wirklich getan!

8. März 2017 Posted by Katrin Benteler

Welch gloreiche Zeiten nun anbrechen werden!

Unsere Domino und XPages Entwickler werden sich den heutigen Tag jedenfalls rot im Kalender anstreichen. Die kritischen Stimmen innerhalb des ITWU-Teams haben die letzten Wochen gewettert: Das traut sich die IBM gar nicht! Aber doch, sie haben es wirklich getan: Das neueste Feature Pack von Notes und Domino, FP8, enthält endlich das lang herbeigesehnte Java-Update für den Domino Server auf die Version 1.8!

Notes und Domino 9.0.1. FP8 steht seit gestern auf Fix Central zum Download bereit - witzig: auf Fix Central, obwohl es ja gar kein Fix Pack mehr ist ;-) Aber natürlich enthält das Feature Pack 8 nicht nur so bahnbrechende neue Features wie das Java-Update, sondern auch viele gelöste Bug Fixes. Welche Probleme genau gelöst wurden, erzählt euch die Fix List:

Notes/Domino Fix List

Aber nun zu den tollen neuen Features, die es neben dem Java-Update noch ins FP 8 geschafft haben:

  1. Bisher wurde die Struktur von Views - also wie die Daten in eurem Notes Client angezeigt und sortiert werden - in der entsprechenden Datenbank gespeichert, was in der Datenbank zusätzlichen Speicherplatz in Anspruch genommen hat. Für Datenbanken, die extrem viele Views beinhalten, konnte das schonmal heißen, dass die Views mehr Speicherplatz verbraucht haben, als die konkreten Daten. Nun habt ihr die Möglichkeit, die Speicherung der Views auszulagern, so dass zum einen der Datenbank mehr Speicherplatz für die Daten zur Verfügung steht. Zum anderen könnt ihr auf diesem Wege sicherstellen, dass nur noch die konkreten Daten der Datenbank im Backup gespeichert werden und nicht mehr die für das Backup unwichtigen Views.
  2. Die uralten Begrenzungen für Entwickler, wie viel Text in einem Notes Dokument gespeichert werden darf wurde endlich von 64 KB auf 16 MB hochgesetzt.
  3. Außerdem können wir jetzt mit Hilfe der Bootstrap 3.3.7 Unterstützung in der XPages Extension Library auch responsive XPages entwickeln.
  4. Für die SAML-Authentifizierung des Domino Servers wird nun die Version von ADFS 3.0 (Active Directory Federation Services) unterstützt. Damit lassen sich jetzt auch Windows Server 2012 R2 anbinden.
  5. Für Notes-Neulinge, die sich eventuell durch die Notes-Namen verwirren lassen könnten, gibt es auch noch ein kleines neues Feature, mit dem man sich standardmäßig die Internetadressen von Absendern und Empfängern von Mails und Kalendereinträgen anzeigen lassen kann.

Weitere Features werden ebenfalls in der Fix List beschrieben.

Vor allem das Java-Update und die Erhöhung der Text-Begrenzung innerhalb von Notes Dokumenten von 64KB auf 16 MB gibt uns ein deutliches Zeichen, dass IBM sich endlich der alten Probleme in Notes und Domino annimmt und die Lösungen für die Zukunft bzw. erstmal für die Gegenwart fit macht.

Bevor ihr aber auf Notes und Domino FP8 updated, solltet ihr sicher gehen, dass ihr diese beiden Versionen schon installiert habt:

  • IBM Traveler 9.0.1.16
  • IBM Mail Support for Microsoft Outlook 2.0.1.4

Herunterladen könnt ihr die unterschiedlichen Versionen unter dem folgenden Link. Der Download für die aktuelle Traveler Version, wird euch beim Download des Domino Servers angeboten. Für die neueste Version von IMSMO geht ihr auf den entsprechenden Reiter.

Download Options for Notes & Domino 9.0.1 Fix & Feature Packs

Solltet ihr Fragen zu den neuen Features oder zum Update auf 9.0.1. FP 8 haben, schreibt uns einfach eine E-mail an info@itwu.de oder ruft uns an unter 05251 288160.

 

 

Domin & REST: Debug your Plugin

7. März 2017 Posted by Sven Hasselbach

When developing OSGi Plugins, you should have your own development server running on your local machine. Not only because of the faster deployment of changes (a new version of a plugin must always deployed with a HTTP restart), but because of the Java debugging posibilities: Only one Eclipse instance can connect to the JVM, and every request processed by the server will start the debugger. If multiple users a accessing the server while you are debugging, your Eclipse will try to debug every incoming request, and this can lead into a confusing situation for all.

To enable debugging, you first have to add two parameters to the notes.ini:

JavaEnableDebug=1
JavaDebugOptions=transport=dt_socket,server=y,suspend=n,address=8000

This starts the debugging on port 8000. Feel free to change the value to every port you want. Because of security reasons you should not start debugging on a productive machine.

After restarting the domino server, you can connect to the JVM in your Eclipse IDE by creating a new JVM remote debugging session. Create a new debug configuration…

… choose (1) „Remote Java Application„, (2) give a name to it, (3) select the plugin project, (4) enter the port the server listens, and click on (5) „Apply„.

If you want to connect to your server, you need to start debugging by clicking on the project:

After setting a breakpoint and sending a request to the servlet, Eclipse switches to the Debug perspective where you can look what happens with your servlet.

Sometimes you are connecting to the „wrong“ JVM, because a Java agent is running and/or a DOTS task does it’s job. It’s better to disable these tasks on your development server.

During debugging you are able to hotswap your code, but keep in mind that after a restart of the HTTP JVM all your changes are no longer „installed“. You have to build a new plugin or replace your code during runtime again.

In the next blog post, let’s talk about our development tools.

Domino & REST: Accessing Domino’s Environment / Check Authentication

2. März 2017 Posted by Sven Hasselbach

If we want to access Domino’s Environment, it is the ContextInfo class which gives us all we need. Everything you need to do to use the class is described in an earlier blog post.

The class gives mainly access to the following methods:

Method Description
getDataDirectory() Path to notes data directory
getEnvironmentString(String envName) Returns the environment variable
getServerDatabase() The actual database as NAPI object, if any
getServerVariable(String varName) Variables from the Request, i.e. „QUERY_STRING“
getUserDatabase() The actual database as Domino Java object, if any
getUserSession() The session of the actual user performing the request (
isAnonymous() true if the current user is Anonymous

Keep in mind that the incoming request is independently of any underlying Notes database. In our example, the URI http://your.server/dominorestservlet/helloworld/ does not run inside of a NSF, that’s why the getServerDatabase() and the getUserDatabase() methods returns null.

As a consequence, our servlet does not have any access restriction and is reachable as anonymous. If you want to access a database programatically, the „normal“ Domino access control is intervening again, but we can do the access check by ourself.

To prevent the access to the servlet, I have added a „checkAuthentication“ method to the RestApiServlet class. This method checks if the current user is a) not anonymous and b) a member of the group RESTAPIAccessAllowed. The method throws a NotAuthenticatedException which let’s the servlet return a HTTP 403.

Domino & REST: Consuming JSON

1. März 2017 Posted by Sven Hasselbach

Consuming JSON is as easy as pie: Just create a new method to the RestApiServlet,  add a @POST annotation, and declare the object you want to the parameters of the method:

    @POST
    @Path("/helloworld/")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response postHelloWorld(HelloWorld helloWorld) {
        return Response.ok(helloWorld, MediaType.APPLICATION_JSON).build();
    }

In this example we are using the same URI „/helloworld/„; because we now are using another HTTP method, there is no conflict between the two methods.

Have a look at the parameter of the postHelloWorld method: It is the HelloWorld class which now instantiated and filled automatically from the POSTed JSON data! We can access the object in Java, and in this short example the result is directly returned back in the response.

If we now send a JSON request with a „message“ field…

curl -i -X POST -d "{\"message\": \"foo\"}" \ 
    -H "Content-Type: application/json" \
    http://your.server/dominorestservlet/helloworld/

… the response contains the message we have posted:

Domino & REST: A basic Servlet

28. Februar 2017 Posted by Sven Hasselbach

To have a good starting point when creating RESTful applications on top of Domino, I have created a „Hello World“ example of a JEE Application, based on Apache Wink & Jackson 2.5.0.

The Jackson AnnotaionProcessor is registered into Apache Wink application and is enabled by default, the JAXB processor is also included as the secondary AnnotationProcessor. The benefit of this is that only one global ObjectMapper instance is created and is reused, wich allows a better performance as when you create an own instance of an ObjectMapper for every request.

The servlet is deployed as a Plugin, so you need a working XPages plugin development environment first before you can build it (I won’t get in the details at this time). The code of the servlet can be found in the domino-rest-servlet.plugin project.

First have a look into plugin.xml: This file contains the extension point used by the plugin, which means that this tells the Domino server what is inside and what to do next with the plugin. The extension point is of type „com.ibm.pvc.webcontainer.application“ and allows to run our own JEE application, independently of the XPages runtime. The contextRoot is the URI part on which our application „listens“. The contentLocation is where files are searched when accessed from the browser, and points to the WebContent folder (as you already know, it is the same as in XPages projects when using the package explorer view). Here you can store static files and/or resources if required.

The web.xml file is the servlet configuration and the place where the servlet is registered. With servlet-mappings you can define URI pathes *inside* of the JEE application.

In this example, every request is mapped to the RestServlet servlet when it is send to „http://your.server/dominorestservlet/„. It will be now processed by the class ch.hasselba.dominorestservlet.RestApiApplication, which „knows“ the RestApiServlet because of the @Path annotations.

Our „Hello World“ example is registered for the URI „/helloworld/“ and only for HTTP GET requests. As soon you are opening „http://your.server/dominorestservlet/helloworld/„, an instance of HelloWorld is created and transformed to JSON. The result looks like this:

{"message":"Hello World!"}

During the next blog posts, I will expand this example and explain step by step how a seamless integration in the Domino environment works.

You can find the code here: https://github.com/hasselbach/domino-rest-servlet

Domino & REST: Listeners for Initialization & Destroying of a Servlet

27. Februar 2017 Posted by Sven Hasselbach

If you need to know when your Servlet is initialized or destroyed, you can use a ServletContextListener in your application.

First, create the class AppServletContextListener and implement the javax.servlet.ServletContextListener interface. This provides two methods for capturing the events: contextInitialized and contextDestroyed:

package ch.hasselba.servlet;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class AppServletContextListener
               implements ServletContextListener{

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        System.out.println("ServletContextListener destroyed");
    }

    @Override
    public void contextInitialized(ServletContextEvent event) {
        System.out.println("ServletContextListener started");
    }
}

The ServletContextEvent allows you to access the ServletContext if required.

Now you have to register the listener in your web.xml:

<web-app>
     <listener>
         <listener-class>
             ch.hasselba.servlet.AppHttpSessionListener
         </listener-class>
    </listener>
</web-app>

As soon as you start or stop the HTTP task, the Listener is called, and you can execute some application specific code (i.e. shutdown threads, bring out the garbage, etc.)

Jackson: Skip Objects conditionally

8. Februar 2017 Posted by Sven Hasselbach

I had a simple problem when implementing this brilliant solution in one of my REST applications: As soon I was using @JsonAnyGetter / @JsonAnySetter and the HidableSerializer together, a NPE was thrown during serialization. The Problem occured in Jackson 1.9.13 and even 2.5.0, the latest version usable with the actual Domino JVM.

  • Stack Trace
org.codehaus.jackson.map.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: ch.hasselba.Test["[anySetter]"])
null
    at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:218)
    at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:183)
    at org.codehaus.jackson.map.ser.std.SerializerBase.wrapAndThrow(SerializerBase.java:140)
    at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:158)
    at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
at ch.hasselba.HidableSerializer.serialize(HidableSerializer.java:29)
    at org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:610)
    at org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:256)
    at org.codehaus.jackson.map.ObjectMapper._configAndWriteValue(ObjectMapper.java:2575)
    at org.codehaus.jackson.map.ObjectMapper.writeValueAsString(ObjectMapper.java:2097)
    at ch.hasselba.Demo.main(Demo.java:54)
Caused by: java.lang.NullPointerException
    at org.codehaus.jackson.map.ser.std.MapSerializer.serializeFields(MapSerializer.java:243)
    at org.codehaus.jackson.map.ser.AnyGetterWriter.getAndSerialize(AnyGetterWriter.java:41)
    at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:154)
    ... 7 more

After hours of investigation, a simple solution came up on SO: The default serializer must be resolved, and then the code will work. I just had to override resolve method of my HidableSerializer:

@Override
public void resolve(SerializerProvider serializerProvider) throws JsonMappingException {
    if(defaultSerializer instanceof ResolvableSerializer) {
         ((ResolvableSerializer)defaultSerializer).resolve(serializerProvider);
    }
}

Here is a complete working example:

 

  • The Demo Code
package ch.hasselba;

import org.codehaus.jackson.Version;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.introspect.BasicBeanDescription;
import org.codehaus.jackson.map.module.SimpleModule;
import org.codehaus.jackson.map.ser.BeanSerializerModifier;

public class Demo {

    public static void main(String[] args) {

        ObjectMapper mapper = new ObjectMapper();

        // register the module
        Version version = new Version(1, 0, 0, "SNAPSHOT");
        mapper.registerModule(new SimpleModule("HidableModule", version) {
            @Override
            public void setupModule(SetupContext context) {
                super.setupModule(context);
                context.addBeanSerializerModifier(new BeanSerializerModifier() {
                    @SuppressWarnings("unchecked")
                    @Override
                    public JsonSerializer<?> modifySerializer(SerializationConfig config, BasicBeanDescription desc,
                        JsonSerializer<?> serializer) {
                        if (IHidable.class.isAssignableFrom(desc.getBeanClass())) {
                            return new HidableSerializer<Object>((JsonSerializer<Object>) serializer);
                        }
                        return serializer;
                    }
                });
            }
        });

        // the data
        String content = "{ \"foo\": \"bar\" }";

        // build the Object
        Test test = null;
        try {
            test =  mapper.readValue(content, Test.class);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // and now convert it back to a String
        String data = null;
        try {
             data = mapper.writeValueAsString(test);
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println( data );

    }

}

 

  • Test Class
package ch.hasselba;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.codehaus.jackson.annotate.JsonAnyGetter;
import org.codehaus.jackson.annotate.JsonAnySetter;

public class Test implements IHidable {

    private Map<String, Object> others = new ConcurrentHashMap<String, Object>();

    @JsonAnyGetter
    public Map<String, Object> getOthers() {
        return this.others;
    }

    @JsonAnySetter
    public void addOther(final String name, final Object value) {   
        this.others.put(name, value);
    }

    @Override
    public boolean isHidden() {
        return false;
    }

}

 

  • Hideable Serializer
package ch.hasselba;

import java.io.IOException;

import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;

public class HidableSerializer<T> extends JsonSerializer<T> {

    private JsonSerializer<T> defaultSerializer;

    public HidableSerializer(JsonSerializer<T> serializer) {
        defaultSerializer = serializer;
    }

    @Override
    public void serialize(T value, JsonGenerator jgen, SerializerProvider provider)
            throws IOException, JsonProcessingException {

        if( value instanceof IHidable ){
            IHidable hidableValue = (IHidable) value;
            if( hidableValue.isHidden() )
                return;
        }
        defaultSerializer.serialize(value, jgen, provider);
    }

   @Override
   public void resolve(SerializerProvider serializerProvider) throws JsonMappingException {
       if(defaultSerializer instanceof ResolvableSerializer) {
            ((ResolvableSerializer)defaultSerializer).resolve(serializerProvider);
       }
   }
}

 

  • IHidable Interface
package ch.hasselba;

public interface IHidable {
    boolean isHidden();
}

Java NAPI: Enable / Disable Recycling of C Handles

6. Juli 2016 Posted by Sven Hasselbach

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.

XPages & Domino JNA

24. Juni 2016 Posted by Sven Hasselbach

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-jnatargetlib“ (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

Neues Sicherheitsupdate für IBM Java

10. Juni 2016 Posted by Arnd Koch

Lotus NotesLotus Domino
Eine Neue Version der IBM JVM für Domino Server schließt einige Sicherheitslücken:
http://www-01.ibm.com/support/docview.wss?uid=swg21984678





Downloadlink für die Updates: https://www-945.ibm.com/support/fixcentral/




Neues Sicherheitsupdate für IBM Java

10. Juni 2016 Posted by Arnd Koch

Lotus NotesLotus Domino
Eine Neue Version der IBM JVM für Domino Server schließt einige Sicherheitslücken:
http://www-01.ibm.com/support/docview.wss?uid=swg21984678





Downloadlink für die Updates: https://www-945.ibm.com/support/fixcentral/