XPages: Running Google’s Chrome V8 Javascript Engine (2)

A while ago I tried to run Google’s V8 Javascript engine on top of XPages, and today I found the reason why my server crashed after the first click: I have tried to load the engine only once (statically), and that killed Domino completly.

Today I moved the code back into the processAction method, and now it works without problems.

package ch.hasselba.xpages.jav8;

import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class JAV8Test implements javax.faces.event.ActionListener {

    public void processAction(ActionEvent actionEvent)
            throws AbortProcessingException {

        ScriptEngineManager factory = new ScriptEngineManager();
        ScriptEngine engine = factory.getEngineByName("jav8");

        try {
            System.out.println(engine.getClass().getCanonicalName());
            engine.eval("var i=1+1;");
            System.out.println("i = " + engine.get("i"));
        } catch (ScriptException ex) {
            ex.printStackTrace();
        }
    }
}
Veröffentlicht unter ServerSide JavaScript, XPages | Verschlagwortet mit , , , , , | 2 Kommentare

XPages: Empty HTML5 Attibutes & PassThroughTags

A while ago I developed some HTML5 XPages applications, but the development process was a little bit frustrating because of the missing possibility to add empty attributes to a PassThroughTag.  A single empty attribute is not allowed, because this would result in invalid XML, and you cannot use “xp:attributes” with “UIPassThroughTag” components.

A simple example like this…

<input type="text" value="John Doe" disabled />

… always ended up in something like this:

<xp:text tagName="input" disableTheme="true">
   <xp:this.attrs>
      <xp:attr name="disabled" minimized="true" value="disabled" />
      <xp:attr name="value" value="John Doe" />
   </xp:this.attrs>
</xp:text>

To fit my requirements, I had extended the “UIPassThroughTag” with a special attribute named “emptyAttrs“. This allowed me to write the example above in the following syntax:

<input type="text" value="John Doe" emptyAttrs="disabled" />

(Multiple empty attributes can be added comma separated.)

Here is the Java class:

package ch.hasselba.xpages;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;

import com.ibm.xsp.component.UIPassThroughTag;
import com.ibm.xsp.renderkit.html_basic.PassThroughTagRenderer;
import com.ibm.xsp.webapp.XspHttpServletResponse;

public class PassThroughTagRendererEx extends PassThroughTagRenderer {

    private final static String EMPTY_ATTRIBUTE_NAME = "emptyAttrs";
    
    public void encodeBegin(FacesContext fc, UIComponent uiComponent)
            throws IOException {

        // Component is rendered?
        if (uiComponent.isRendered() == false) {
            return;
        }
        
        // only process instances of UIPassThroughTags
        if ((uiComponent instanceof UIPassThroughTag)) {
            
            UIPassThroughTag uiPTTag = (UIPassThroughTag) uiComponent;
            
            ResponseWriter rw = fc.getResponseWriter();
            
            // grab the printer writer directly from the response
            XspHttpServletResponse response = (XspHttpServletResponse) 
                fc.getExternalContext().getResponse();

            PrintWriter rwPrinter = response.getWriter();
            
            // start the element tag
            rw.startElement(uiPTTag.getTag(), uiComponent);
            
            // process all attributes
            List<UIPassThroughTag.TagAttribute> attrList = uiPTTag
                    .getTagAttributes();
            
            if (attrList != null) {

                UIPassThroughTag.TagAttribute tagAttribute = null;
                String attrName = null;
                String attrValue = null;

                for (int i = 0; i < attrList.size(); i++) {
                    tagAttribute = attrList.get(i);
                    attrName = tagAttribute.getName();
                    attrValue = tagAttribute.getValue();
                    if (EMPTY_ATTRIBUTE_NAME.equalsIgnoreCase(attrName)) {
                        
                        // process all empty tags
                        String tags[] = attrValue.split(",");
                        for( int j=0; j<tags.length; j++){
                            // write the attribute name only
                            rwPrinter.write( " " );
                            rwPrinter.write( tags[j].trim() );
                        }
                    }else{
                            // write the attribute data
                            rw.writeAttribute(attrName, attrValue, null);
                    }
                }
                
            }
        } else {
            // process other instances "as always"
            super.encodeBegin(fc, uiComponent);
        }
    }

}

To activate the class you have to overwrite the renderer in the “faces-config.xml“:

<?xml version="1.0" encoding="UTF-8"?>
<faces-config>
  <render-kit>
    <renderer>
      <component-family>javax.faces.Output</component-family>
      <renderer-type>com.ibm.xsp.PassThroughTagRenderer</renderer-type>
      <renderer-class>ch.hasselba.xpages.PassThroughTagRendererEx</renderer-class>
    </renderer>
  </render-kit>
</faces-config>
Veröffentlicht unter HTML5, XPages | Verschlagwortet mit , , , | 2 Kommentare

REST & Security: Why HTTP GET is insecure (and the other methods too)

Yesterday René commented that submitting username and password with HTTP GET is insecure, because they are submitted in clear text over the wire as part of the URI.

At the first moment, I did not give some thought about it, because it is known fact that data added to an URI are less secure. They are added to the browser history, are logged in the requests on servers, and every proxy between the user’s browser and the requested server are seeing (and maybe logging) these URI’s too. That’s why HTTP GET is problematic: The credentials are accidentially spread over the whole world, like any other information which are appended to an URI.

In René’s example, he pointed out that a hotspot provider of a public WiFi can easily grab the URIs (and the credentials), and that’s the reason why HTTP GET is insecure. But this is not the whole truth: As soon HTTP data are going over the wire, the data can be fetched from anyone in the chain of the transport, and it doesn’t matter which HTTP method is used.

Some clever guys are running TOR exit nodes and grab the whole traffic through a transparent proxy, and because they have access to the whole traffic, they are able to fetch credentials from these requests. As long as the data are unprotected.

To protect your data, you have two choices: Use HTTPS connections or encrypt the data by yourself (f.e. with JWE). Manually encrypting won’t solve the problem of logging, but it can help to secure the data. But the preferred way is first one, because it solves all the problems of insecure data during their transport, and is really easy to implement. TLS / SSL is a layer between the TCP layer and the HTTP layer, and the whole traffic (the HTTP data) is encrypted. This includes the URI, only the target host is known to everyone involved of the transport

You shouldn’t use HTTP GET to transfer sensitive informations. The browser history is problematic, and the logs on the target server would contain the requested URIs. When developing a RESTful API you must bear this in mind.

Veröffentlicht unter REST, Security, Server, Web | Verschlagwortet mit , , , | 2 Kommentare

REST & Security: More about the DominoStatelessTokenServlet

During the last days I have refined the DominoStatelessTokenServlet a little bit. It is now a pre-beta release, and I think it is time to explain some details about it. While it is still a proof-of-concept, it demonstrates how a stateless authentication can easily be implemented. A lot of testing is still required until it is ready for production use, but I think it provides really cool things for the domino environment.

First, it fixes the problematic 200er HTTP response code when an authentication was not successfull. Then it introduces a higher security level for web based applications, because the authentication token is only transferred in the HTTP headers: A CSRF attack as shown here is not possible anymore. The authentication works accross multiple servers / clusters, which can become interesting for example when you want to share the authentication securely between a Bluemix hosted application and your companies hosted infrastructure; the token is created from a server running in your company, and is then used to identify a user in the cloud-based application (It’s a real authentication, not a “misused authorization” like OAuth).

The token can also be safely stored in an mobile app: When the device gets lost, the user credentials are not compromised. And it allows to create different tokens for different applications for the same user (currently not implemented).

As a short demonstration, I have added a Angular JS example (with a hardcoded token) to  show how it works in practise: An AJAX request is sent to the servlet, and the JSON response contains the name of the current Domino user.

The HTML page is not really complicated, it will just show the returned username:

<!doctype html>
<html ng-app>
   <head>
      <title>Hello AngularJS</title>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
      <script src="hello.js"></script>
   </head>
   <body>
      <div ng-controller="Hello">
         <p>Hello {{greeting.username}}!</p>
      </div>
   </body>
</html>

The “Hello” controller which performs the AJAX request adds the “X-AUTH-TOKEN” to the HTTP headers of the request:

function Hello($scope, $http) {

   // add a valid token to the headers
   $http.defaults.headers.common['X-AUTH-TOKEN'] = 
     'MTQyNDI2OTE0NDgxNCFUVGVzdFVzZXIwMQ==!HyC1mnvvdaneLaW0Wn48kZ1MaTrdowr1e4nWBRWRX8Y=';

   // load the data
   $http.get('http://localhost/token/validate/').
      success(function(data) {
         $scope.greeting = data;
      });

}

And this is the result:

StatelessToken 01 - Validate Token

The Token consist of two parts: The data part, and the Hmac hash of the data. Both are Base64 encoded, and when the data part is decoded, you can currently see the username and the timestamp of the token generation:

  • Encoded
MTQyNDI2OTE0NDgxNCFUVGVzdFVzZXIwMQ==
  • Decoded
1424269144814!TTestUser01

Because the data are hashed it is not possible to modify them. The timestamp is validated from the servlet; as soon it is too old, it is not longer valid.

To create a token, the servlet must be currently opened with the username and the password as URL parameters:

http://localhost/token/create/?username=TTestUser01&password=test01

In the response, the newly generated token is added to the HTTP headers:

StatelessToken 02 - Create Token

In the servlet configuration (web.xml), a backend user is defined on whose behalf a lookup to the NAB is made to verify the provided HTTP password.  The password for the hash is also stored there, and the maximum age of the token.

Veröffentlicht unter Allgemein, Java, REST, Security, Web | Verschlagwortet mit , , , , , , , , | 12 Kommentare

REST & Security: A Stateless Token Servlet

I have uploaded some of my projects to GitHub, including an alpha version of a stateless token servlet.

The servlet has it’s own authentication mechanism (the password is currently not validated), and for developing purposes it uses HTTP GET. In a future release, the token will be transfered as a HTTP header. Additionally, the HTTP method will be changed to POST. Last but not least must the code be optimized. For example there is no recycling implemented at this moment, and there is a dubious bug in the token validation (which was solved by encoding it to Base64 and back again).

  • Generate a Token

To generate a new token, you have to open the servlet with the following URL format:

"/create?username=<CANONICAL USER>&password=<WHATEVER>"

Example for “CN=Sven Hasselbach/OU=Hasselba/O=CH

http://example.com/token/create/?username=CN%3DSven%20Hasselbach%2FOU%3DHasselba%2FO%3DDE&password=XXX

This will return a JSON string containg the newly generated token:

{token: 'MDkgRmViIDIwMTUgMjI6NDk6MTIuMzU2IUNOPVN2ZW4gSGFzc2VsYmFjaC9PVT1IYXNzZWxiYS9PPURF!9s7dSS7F67hSS/lLODZHVM0NsTR4IurkZtjiysGzoWA='}

The Token is a Base64-encoded String containing a Timestamp, the Username and a Hmac Hash and only valid for one hour.

  • Validate a Token

To validate the token, you can use the URL

/validate/?token=<token>

Example:

http://example.com/token/validate/?token=MDkgRmViIDIwMTUgMjI6NDk6MTIuMzU2IUNOPVN2ZW4gSGFzc2VsYmFjaC9PVT1IYXNzZWxiYS9PPURF%219s7dSS7F67hSS%2FlLODZHVM0NsTR4IurkZtjiysGzoWA%3D

If the token is valid, a new “NotesSession” is created for the given user. The server response contains a JSON String with the current “EffectiveUserName”:

{user: 'CN=Sven Hasselbach/OU=Hasselba/O=CH'}

Because the servlet creates its own session, you can be logged in as a different user: The Domino authentication is not affected by the servlet.

Veröffentlicht unter Java, REST, Security, Web | Verschlagwortet mit , , , , | Hinterlasse einen Kommentar

IBM Bluemix: Filemode-Problems with GitHub

When creating your own build pack for IBM Bluemix applications (or other Cloud Foundry based solutions), it is required to set the correct file mode for the executables before initially pushing them to GitHub. Otherwise the compilation will fail, and it seems to be a known bug for GitHub based repositories that the mode cannot be changed later.

The command for this is

git update-index --chmod=+x <path-to-file>

You can see the result when you commit the files to your respository:

> git commit -m "first commit"

[master (root-commit) 680979a] first commit
 4 files changed, 34 insertions(+)
 create mode 100644 README.md
 create mode 100755 bin/compile
 create mode 100755 bin/detect
 create mode 100755 bin/release

[The three files in the folder “/bin” have the correct mode 755 instead 644]

You can find an example build pack here https://github.com/hasselbach/cf-buildpack-basic.git.

Veröffentlicht unter IBM Bluemix | Verschlagwortet mit , , | Hinterlasse einen Kommentar

REST & Security: Same-Origin Policy / CORS

The “Same-orginin policy is an important concept for protecting web applications. In short, only resources from the same domain are allowed, everything else is permitted. To allow access other domains in your application, you have to enable CORS, a tutorial how to enable this on a Domino server was written by Mark Barton a while ago.

It works fine for protecting an applications against DOM manipulations and/or injection of malicous script code, but this client side security restriction only blocks the response from the server. The client still sends a request, and this can be problematic for the security of a RESTful application.

To clearify this, here is a short example:

I have created a small HTML page containing an Ajax request to load some code of a XPages-based REST service on another server. This file is hosted on my hasselba.ch server, and wants to access some data on my local Domino server:

<html>
   <body>
   <h1>SOP Demo</h1>
   <script>
      var xhr =(window.XMLHttpRequest)?new XMLHttpRequest():
          new ActiveXObject("Microsoft.XMLHTTP");

      xhr.open("GET","http://localhost/REST.nsf/SOPDemo.xsp/foo/",true);
      xhr.withCredentials = true;
      xhr.send();
   </script>

   </body>
</html>

The “withCredential” options ensures that an eventually existing Domino session is used when performing the request.

The REST service on my Domino server prints the actual username to the console:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view
    xmlns:xp="http://www.ibm.com/xsp/core"
    xmlns:xe="http://www.ibm.com/xsp/coreex"
    rendered="false">
    
    <xe:restService
        id="restService"
        pathInfo="foo">
        <xe:this.service>
            <xe:customRestService
                requestContentType="application/json"
                requestVar="data">             
                <xp:this.doGet>
                   <![CDATA[#{javascript:
                      print("Hello '" + session.getEffectiveUserName() + "'");
                      "{}"
                   }]]>
                </xp:this.doGet>
             </xe:customRestService>
         </xe:this.service>
     </xe:restService>
</xp:view>

When opening this page, the response of the request is blocked, and that’s what the “Same-origin policy” was made for: If the response contains malicious Javascript code, this script won’t get executed.

01

The client is protected, but what about the request send to the server?

02

The request was made with my credentials, and that is why the “Same origin-policy” does not protect RESTful applications: If a victim visits my page, I am able perform malicious requests against a RESTful webservice in his context.

Veröffentlicht unter Java Script, REST, Security, Web | Verschlagwortet mit , , , | Hinterlasse einen Kommentar

Raspberry Pi vs. IBM Bluemix – 1:0

I had some time last night (the whole family had gone to bed early), so I spent some to look at the XPages integration into Bluemix. I found the Greenwell Travel Expenses Demo:

Bildschirmfoto 2015-01-28 um 10.24.41

But after clicking a link, the page returned an error:

Bildschirmfoto 2015-01-28 um 10.00.21

Hmm…But I wanted to see the application!

That’s why I checked, if the datasources are protected. I recommend this for years. Fredrik Norling wrote a little snippet for this. Or better use the “ignoreRequestParam“. Then all your problems are gone.

http://greenwellexpenses.mybluemix.net/bluemix/Expense-App-Design.nsf/teamExpenses.xsp?databaseName=homepage.nsf

Bingo! Unprotected!

Bildschirmfoto 2015-01-28 um 10.15.29

I now was able to see a little bit more of the application and to check the underlying environment. But then came the moment where my brain forced me to try out some things:

First, I had to look again on the IP address in the error page: “109.228.14.66“. This is not an  internal address. Let’s check it:

Bildschirmfoto 2015-01-28 um 10.34.08

Not reachable. Whois for “109.228.14.66” ? “Fasthosts Internet Limited“. A provider in UK.

A ping to “greenwellexpenses.mybluemix.net” returned “75.126.81.6″, which belongs to Softlayer. The server is allowed access other servers? Maybe the application can call me?

Bildschirmfoto 2015-01-28 um 10.58.56

Yes, the application can:

Bildschirmfoto 2015-01-28 um 11.09.41

Unbenannt

Now I can try to DoS the application.  Because the outgoing connection from the application waits for a response (think about “telnet www.example.com 80“), I can create a bunch of requests, and the server will quickly reach it’s limit.

That’s why I created a simple bash script which makes HTTP request to the Bluemix instance. The script runs on a Raspberry Pi, to demonstrate the low demand of hardware requirements and to show how easy it is do make a DoS attack against a XPage application (if it is was not developed under security aspects).

Here is a short video (the source of the bash script is NOT shown, but it has fewer then 10 lines of code):

This was a “friendly” attack. I have not done anything harmfull. And this is a demo app; if it is not secure, this is not a real problem. The application is available again ten minutes later.

But last night I searched for some XPages servers in the WWW, and I found a lot of misconfigured systems: Error Page enabled, the “Ignore request parameter” is not set to “true” or at least the hack from Fredrik running. And the servers are allowed to access the whole internet… Dev’s and Admins should do their jobs better!

If you plan to migrate your apps to the cloud, please learn more about security. Or hire some specialists with the knowledge and experience in this sector. It is worth the time and the money.

Veröffentlicht unter Security, Web, XPages | Verschlagwortet mit , , , , | 6 Kommentare

HowTo: Vaadin on Domino (4)

Now, let’s access some Domino resources.

I have created a database named “VaadinResources.nsf“, containing a normal image resource, and an image added via package explorer to the “WEB-INF” folder:

Screenshot - ImageResource

Screenshot - WEB-INF Resource

Vaadin provides stream resources, which allows creating of dynamic resources. These resources handle “InputStream” objects, which we can grab from Domino via Java NAPI.

To do this, it is first required to add some plug-ins to the dependencies of the “HelloVaadin” plug-in:

Screenshot - Dependencies

  • com.ibm.domino.napi
  • com.ibm.domino.commons
  • com.ibm.commons

Then we can import the “NAPIUtils” class to the project and add a new method “loadBinaryFile” to it:

/**
 * loads given file from a database and returns the Inputsstream
 * 
 * @param serverName
 *            the server to use
 * @param dbPath
 *            the database path
 * @param fileName
 *            the file to load
 * @return the file data as InputStream
 * 
 */
static public InputStream loadBinaryFile(final String serverName, final String dbPath,
        final String fileName) {

    NotesSession nSession = null;
    NotesDatabase nDatabase = null;
    NotesNote nNote = null;

    try {
        nSession = new NotesSession();

        // open database
        try {
            nDatabase = nSession.getDatabaseByPath(serverName + "!!" + dbPath);
        } catch (NotesAPIException e) {
            e.printStackTrace();
        }
        nDatabase.open();

        // load existing data
        nNote = FileAccess.getFileByPath(nDatabase, fileName);

        // get Filedate and return String
        InputStream is = FileAccess.readFileContentAsInputStream(nNote);

        return is;
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        // recycle NAPI objects
        recycleNAPIObject(nNote, nDatabase, nSession);
    }
    return null;
}

A new class “DominoImageSource” which implements the “StreamResource.StreamSource” interface uses this method to pipe the “InputStream” object returned from the Domino Java NAPI:

package ch.hasselba.vaadin;

import java.io.InputStream;
import ch.hasselba.napi.NAPIUtils;
import com.vaadin.server.StreamResource.StreamSource;

@SuppressWarnings("serial")
public class DominoImageSource implements StreamSource {
    
    private String fileName;
    private String serverName;
    private String dbPath;
    
    public DominoImageSource(final String serverName, final String dbPath, 
            final String fileName){
        super();
        this.serverName = serverName;
        this.dbPath = dbPath;
        this.fileName = fileName;
    }
    public InputStream getStream () {    
        return NAPIUtils.loadBinaryFile( this.serverName, this.dbPath, this.fileName );
    }
}

Now, we can create a new Application named “ResourceUI” which displays these two resources:

package ch.hasselba.vaadin;

import com.vaadin.server.StreamResource;
import com.vaadin.server.StreamResource.StreamSource;
import com.vaadin.server.VaadinRequest;
import com.vaadin.ui.Image;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;

@SuppressWarnings("serial")
public class ResourcesUI extends UI  {

    @Override
    protected void init(VaadinRequest request) {
        
         VerticalLayout layout = new VerticalLayout();
         setContent(layout);
         layout.setSizeFull();
         
         // Create an instance of our stream source.
         StreamSource webinfResource = new DominoImageSource ( 
                 "Dev01", "VaadinResources.nsf" , "/WEB-INF/WEB-INFResource.png");
         
         StreamSource imageResource = new DominoImageSource ( 
                 "Dev01", "VaadinResources.nsf" , "ImageResource.gif");

         // Create an image component that gets its contents
         // from the resource.
         layout.addComponent(new Image("WEB-INF Resource", 
                 new StreamResource(webinfResource, "image01.png")));
         layout.addComponent(new Image("Image Resource", 
                 new StreamResource(imageResource, "image02.gif")));
        
    }
}

Again, no rocket science and self-explaining code. When we open the application, the resources are loaded from the database and displayed in the browser:

Screenshot - Resource Application

As soon we are changing the images in the database (and the cache is expired), the new image will appear in our Vaadin application.

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

HowTo: Vaadin on Domino (3)

Let’s create another application, based on Vaadin’s AddressBook example. You can download the source code directly or grab the code from the repository; it is a single class file named “AddressbookUI” only.

After importing (or manually creating) the class in the HelloVaadin plug-in, the servlet configuration in “web.xml” must be updated:

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

  <display-name>Addressbook</display-name>
    <context-param>
        <description>Vaadin production mode</description>
        <param-name>productionMode</param-name>
        <param-value>false</param-value>
    </context-param>
    
    <servlet>
        <servlet-name>AdressbookServlet</servlet-name>
        <servlet-class>com.vaadin.server.VaadinServlet</servlet-class>
        <init-param>
            <param-name>UI</param-name>
            <param-value>ch.hasselba.vaadin.AddressbookUI</param-value>
        </init-param>
    </servlet> 

    <servlet-mapping>
        <servlet-name>AdressbookServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    
</web-app>

The “<param-value>” must contain the complete class name, I have additionally changed the name of the servlet and updated the path in the “plugin.xml“:

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>

     <extension
         point="com.ibm.pvc.webcontainer.application">
      <contextRoot>
         /addressbook  
      </contextRoot>
      <contentLocation>
         WebContent
      </contentLocation>
   </extension>

</plugin>

To connect the example to a Domino environment, the “createDummyDatasource” method of the class must be replaced:

@SuppressWarnings("unchecked")
private static IndexedContainer createDummyDatasource() {

    // Domino objects
    Session session = null;
    Database db = null;
    View view = null;
    Document doc = null;
    Document tmpDoc = null;

    // initialize IndexedContainer
    IndexedContainer ic = new IndexedContainer();

    // add fieldnames as properties
    for (String p : fieldNames) {
        ic.addContainerProperty(p, String.class, "");
    }

    // get all users from NAB
    try{
        // init Domino objects
        session = ContextInfo.getUserSession();
        db = session.getDatabase(session.getServerName(), "dummynames.nsf");
        view = db.getView( "People" );

        // process all documents in view
        doc = view.getFirstDocument();
        while (doc != null) {

            // create a new item
            Object id = ic.addItem();

            // add field values to the item
            ic.getContainerProperty(id, FNAME).
                setValue(doc.getItemValueString("FirstName"));
            ic.getContainerProperty(id, LNAME).
                setValue(doc.getItemValueString("LastName"));

            // grab next document
            tmpDoc = doc;
            doc = view.getNextDocument(tmpDoc);
            recycle( tmpDoc );
        }
    }catch(Exception e){
        e.printStackTrace();
    }finally{
        recycle( doc, tmpDoc, view, db, session );
    }
    return ic;
}

/**
* recycle Domino objects
*
* @param objs
*     lotus.domino.Base objects to recylce
*/
private static void recycle(Base... objs){
    try{
        for( Base obj:objs ){
            if( obj != null )
                obj.recycle();
        }
    }catch(Exception e){}
}

Because this is not rocket science I won’t get into the details.

To prevent anonymous access, I have added a simple redirection in the “init” method:

protected void init(VaadinRequest request) {
        
    if( ContextInfo.isAnonymous() ){
         getPage().setLocation("/names.nsf?login=1&redirectto=" + 
             request.getContextPath() );
         return;
    }
        
    initLayout();
    initContactList();
    initEditor();
    initSearch();
    initButtons();
}

When opening the application as an anonymous user you will be automatically redirected to the Login Screen:

00 - Login

After signing in, domino redirects back to the addressbook example, and the list of persons in your “names.nsf” is shown up:

00 - Addressbook

Veröffentlicht unter OSGi, Vaadin | Verschlagwortet mit , , | 1 Kommentar