Posts Tagged: ‘xpages’

XPages: Interactive Maps using OpentStreetMap and Leaflet.js

4. Mai 2015 Posted by Heiko Voigt

Hi there, it's been a while since my last coding post but over the past rainy weekend, I had a bit of time on my hands to build an XPages App that shows marker data coming from a Domino Database as ...

42. DNUG Konferenz: Preview auf den Techniktrack Entwicklung

28. April 2015 Posted by Roswitha Boldt

Track 2.4: Technik - Entwicklung

11. Juni 2015, 8:30 bis 15:45 Uhr

 

Integration von Salesforce und IBM Software - Andreas Rosen, QKom GmbH
Domino im Dialog mit einer OpenSource-Workflow-Engine - Jens Ribbeck / Veit Weber, ULC Business Solutions GmbH

Speed up your development in XPages or Javascript using Open Source - Tim Clark, Teamstudio (angefragt)

Vom XPages Held zum OSGI Guru! Wie man eine Extension Library entwickelt. Christian Güdemann, WebGate Consulting AG
XPages auf Bluemix - Niklas Heidloff, IBM


Track Manager sind Oliver Busse, We4IT GmbH, und Thorsten Hindermann, GWDG.

 

Hier erfahren Sie mehr über die 42. DNUG Konferenz in Dortmund:

Überblick

Preview der Tracks

Anmeldung als Teilnehmer

Übersicht über Sponsoren und Aussteller mit Kontaktmöglichkeit

 

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

10. April 2015 Posted by Sven Hasselbach

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();
        }
    }
}

XPages: Empty HTML5 Attibutes & PassThroughTags

10. März 2015 Posted by Sven Hasselbach

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>

Notes-Funktionen in JavaScript

6. März 2015 Posted by Lars Buntrock

Spätestens seit XPages Einzug in den Entwicklungsprozess von Notes Applikationen gehalten haben, müssen sich Entwickler zwangsläufig mit Web-Entwicklungstechnologien auseinandersetzen, u. a. auch mit JavaScript. Da gerade das Entwicklercamp 2015 zu Ende gegangen ist, hoffe ich, dass sich der Eine oder Andere hat begeistern lassen, neben der klassischen Notes-Entwicklung der Web-Seite (und hier insbesondere der XPages […]

EntwicklerCamp 2015: XPages – WebServices und REST

4. März 2015 Posted by Bernd Hort

EntwicklerCamp

Der letzte Tag des EntwicklerCamps ist gekommen. Heute war mein zweiter Vortrag zum Thema "XPages - WebServices und REST". In 90 Minuten habe ich ausführlich beschrieben, wie Webservices und RESTful Webservices innerhalb von XPages konsumiert werden können. Die erste Hälfte des Vortrages konzentrierte sich auf das Backend mittels Java. In der zweiten Hälfte habe ich den Blick auf JavaScript im Browser gerichtet.

Wie immer können die Folien und die Beispiel-Anwendung heruntergeladen werden. Basis für diesen Vortrag war mein Vortrag auf der IBM ConnectED 2015: BP 108 - Be Open - Use Web Services and REST in XPages Applications. Insofern ist die Beispiel-Anwendung die gleiche wie beim IBM ConnectED-Vortrag.

 

In der Beispiel-Anwendung befinden sich nicht nur XPages, um die Webservices und RESTful Webservices zu konsumieren. Damit die Beispiele auch bei Ihnen ohne Probleme laufen, sind ein Webservice und drei RESTful Webservices implementiert.

EntwicklerCamp 2015: Java Managed Beans

3. März 2015 Posted by Bernd Hort

EntwicklerCamp

Der zweite Tag des EntwicklerCamps nähert sich dem Ende. Heute war mein Vortrag "Java Managed Beans". Nach einer kurzen Einführung in Java Managed Beans haben wir uns die Verwendung in XPages angesehen. Wobei gerade auch das Verständnis für die internen Abläufe in der XPages-Laufzeitumgebung ein wichtiger Aspekt war. Am Schluß wurden die Einsatzmöglichkeiten diskutiert.

Wie immer können die Folien und die Beispiel-Anwendung heruntergeladen werden.


IBM Bluemix für “zu Hause”: Bluemix – Local

26. Februar 2015 Posted by Henning Schmidt

Im vergangenen Jahr hat IBM ihr Platform-as-a-Service (PaaS) Angebot unter dem Namen IBM Bluemix gestartet. Diese Plattform bietet Ihnen die Möglichkeit, Anwendungen zu entwickeln und hosten zu lassen, ohne sich um die Hard- bzw. Middleware kümmern zu müssen. Die komplette Skalierung übernimmt Bluemix nach Ihren Vorgaben für Sie. Sie können zwischen verschiedenen Runtimes wählen (Java, […]

Raspberry Pi vs. IBM Bluemix – 1:0

28. Januar 2015 Posted by Sven Hasselbach

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 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.

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.

IBM ConnectED 2015: BP 108 – Be Open – Use Web Services and REST in XPages Applications

28. Januar 2015 Posted by Bernd Hort

IBM ConnectED 2015

Before I head to the party I will keep my promise and post the presentation and the sample database.

BP 108 - Be Open - Use Web Services and REST in XPages Applications

Thank you to everyone who joined my session.


Autosave when deleting attachments on an XPage

3. Dezember 2014 Posted by Christian Annawald

 

To download attachments in an application and also to be able to delete them, the FileDownload control is used on IBM Domino XPages. Unfortunately, this control comes with a little twist. If you click on the trash can icon to delete the attachment, it looks like the file is actually deleted. But the file is not finally deleted until the XPage is saved.

If you leave the XPage after the click on the trash can icon, without saving the document – after all, the attachment disappeared from the view, so why SHOULD you save the document anyway – and open it some time later again, the file is back.

 

Img. 1: Document including several attachments

 

Img. 2: Document after clicking the trash can icon of the last attachment

 

Img. 3: The last attachment is back again after leaving the document without saving and coming back to it afterwards

 

In order to execute the change, or rather the deletion, directly within the document, it is necessary to add the property setSave(true) to the event handler of the trash can icon. Unfortunately, you cannot do this within the Domino Designer. So a little programming work is needed.

Luckily I have found the appropriate code for most of this work in a discussion comment on stackoverflow by Sven Hasselbach: http://stackoverflow.com/questions/13101615/auto-save-doc-after-delete-of-attachment-in-file-download-control

Unfortunately, the original code always produced the following error when I used it with Notes 9:

X XPAGE ERROR: COM.XSP.IBM.ACTION.ACTIONGROUP INCOMPATIBLE WITH COM.IBM.XSP.ACTIONS.DELETEATTACHMENTSACTION

Therefore, I adjusted the source code, so that it works with Notes 8.5.3 and Notes 9 alike. To use it properly you only need to insert it into the BeforeRenderResponse event of the XPage.

 

<xp:this.beforeRenderResponse>

            <![CDATA[#{javascript:

            function overrideFileDownloadAction( fDownload ){

                        //Check whether the control exists or not

                        if( fDownload === null )

                           return;

                        //Call actual function

                        rekOverrideFileDownloadAction( fDownload, fDownload );

             }

/*

*This control iterates through all children of the FileDownload control

*and seeks the event handler

*/

            function rekOverrideFileDownloadAction( component:javax.faces.component.UIOutput,fDownload:com.ibm.xsp.component.UIFileDownload  ){

                        try{

                                   //Get children of the current element

                                   var children:java.util.List = component.getChildren();

                                   var it:java.util.Iterator = children.iterator();

                                   var curChild:javax.faces.component.UIOutput;

                                   //Loop over all children

                                               while( it.hasNext() ){

                                                         curChild = it.next();

                                                         if( typeof( curChild ) === 'com.ibm.xsp.component.xp.XspEventHandler' ){

                                                         //Event handler found

                                                         //set setSave to true

                                                         // to automatically save after the event

                                                           curChild.setSave(true);

                                               }

                                   //Event handler not found, therefore recursive call to investigate the children

                                   rekOverrideFileDownloadAction( curChild , fDownload );

                                               }

                        }catch(e){}   

            }

           

overrideFileDownloadAction( getComponent( 'IDFILEDOWNLOAD' ) );

//IDFILEDOWNLOAD = the ID of the FileDownload control

    }]]>

</xp:this.beforeRenderResponse>

 

If the above code is inserted into your XPage, the file is automatically saved after clicking on the trash can icon. The disadvantage of this is that it saves the complete document and not just delete the attachment. Therefore, you have to be careful to ensure that you have not previously changed the value of another field that should not be saved.

 

XPages: WebContent Files (3) – Create a Minimizer Servlet

26. November 2014 Posted by Sven Hasselbach

XPages: WebContent Files (2) – Manipulate exitsting files using the Java NAPI

19. November 2014 Posted by Sven Hasselbach

In this article, I will shortly give an overview how you can edit existing file from the WebContent folder (Don’t miss the first article on this topic).

First, let’s create a view to display the design elements of the WebContent folder. To do this, I have an old school LotusScript Agent which updates the selection formula of a view (Some details about this technique can be found here).

Sub Initialize

    Dim session As New NotesSession
    Dim doc As NotesDocument
    Dim db As NotesDatabase
    Dim view As NotesView
      
    Set db = session.Currentdatabase
    Set view = db.Getview("DesignView")
    
    view.SelectionFormula = |@Contains($FlagsExt; "w")|
    
    Set doc = db.GetDocumentByUNID(view.UniversalID)
    Delete view
    
    doc.ReplaceItemValue "$FormulaClass", "7FFF"
    doc.Sign
    doc.Save True, False

End Sub

The agent has to run once to change the view’s selection criteria. In this example the view has the name “DesignView”. After that, we can add a single column to the view to display the files and their names:

Now lets build a simple XPage named Files.xsp to select the file you want to edit:

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

    <xp:viewPanel
        rows="30"
        id="viewPanel1"
        var="rowEntry">
        <xp:this.facets>
            <xp:pager
                partialRefresh="true"
                layout="Previous Group Next"
                xp:key="headerPager"
                id="pager1">
            </xp:pager>
        </xp:this.facets>
        <xp:this.data>
            <xp:dominoView
                var="viewDesign"
                viewName="DesignView">
            </xp:dominoView>
        </xp:this.data>
        <xp:viewColumn
            columnName="$FileNames"
            id="viewColumnFileNames"
            displayAs="link"
            >
            <xp:this.pageUrl>
                <![CDATA[#{javascript:"/Editor.xsp?filename=" +
                   rowEntry.getColumnValues().get(0)}]]>
        </xp:this.pageUrl>
        </xp:viewColumn>
    </xp:viewPanel>
    <xp:br />

</xp:view>

The Files.xsp lists all files as links and opens them via the Editor.xsp XPage:

This is the Editor.xsp:

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

    FileName:
    <xp:inputText
        id="inputTextFileName"
        value="#{fileBean.fileName}"
        defaultValue="#{param.filename}"
        disabled="true" />
    <xp:br />
    FileData:

    <xp:inputTextarea
        id="inputTextarea1"
        value="#{fileBean.fileData}"
        rows="40"
        cols="80" />
    <xp:br />
    <xp:button
        value="Load"
        id="buttonLoad">
        <xp:eventHandler
            event="onclick"
            submit="true"
            refreshMode="complete"
            action="#{fileBean.loadData}">
        </xp:eventHandler>
    </xp:button>
    <xp:button
        value="Save"
        id="buttonSave">
        <xp:eventHandler
            event="onclick"
            submit="true"
            refreshMode="complete"
            action="#{fileBean.saveData}">
        </xp:eventHandler>
    </xp:button>
    
</xp:view>

It uses a simple managed bean…

package ch.hasselba.napi;

import java.io.Serializable;

public class FileDataBean implements Serializable {

    private static final long serialVersionUID = 1L;
    private String fileName;
    private String fileData;
    private String dbPath;
    private String dbServer;

    public String getDbPath() {
        return dbPath;
    }

    public void setDbPath(String dbPath) {
        this.dbPath = dbPath;
    }

    public String getDbServer() {
        return dbServer;
    }

    public void setDbServer(String dbServer) {
        this.dbServer = dbServer;
    }

    public void setFileData(String fileData) {
        this.fileData = fileData;
    }

    public String getFileData() {
        return fileData;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String getFileName() {
        return fileName;
    }

    public void loadData() {
        this.fileData = NAPIUtils.loadFile(this.dbServer, this.dbPath, this.fileName);
    }

    public void saveData() {
        NAPIUtils.saveFile(this.dbServer, this.dbPath, this.fileName, this.fileData);
    }
}

… which is initialized with the properties defined in the faces-config.xml. There you can find the database server and the database path:

<?xml version="1.0" encoding="UTF-8"?>
<faces-config>
  <managed-bean>
    <managed-bean-name>fileBean</managed-bean-name>
    <managed-bean-class>ch.hasselba.napi.FileDataBean</managed-bean-class>
    <managed-bean-scope>view</managed-bean-scope>
    <managed-property>
      <property-name>dbPath</property-name>
      <value>NAPI.nsf</value>
    </managed-property>
    <managed-property>
      <property-name>dbServer</property-name>
      <value>DEV01/Hasselba/CH</value>
    </managed-property>
  </managed-bean>
</faces-config>

And last but not least, the required NAPIUtil class:

package ch.hasselba.napi;

import java.io.InputStream;
import com.ibm.designer.domino.napi.NotesAPIException;
import com.ibm.designer.domino.napi.NotesDatabase;
import com.ibm.designer.domino.napi.NotesNote;
import com.ibm.designer.domino.napi.NotesObject;
import com.ibm.designer.domino.napi.NotesSession;
import com.ibm.designer.domino.napi.design.FileAccess;

public class NAPIUtils {

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

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

        try {
            nSession = new NotesSession();

            // open database
            nDatabase = nSession.getDatabaseByPath(serverName + "!!" + dbPath);
            nDatabase.open();

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

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

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

        return fileName;
    }

    /**
     * loads a given WebContent file and returns the result as String
     * 
     * @param serverName
     *            the server to use
     * @param dbPath
     *            the database path
     * @param fileName
     *            the file to load
     * @param fileData
     *            the data of the file
     */
    static public void saveFile(final String serverName, final String dbPath,
            final String fileName, final String fileData) {

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

        try {
            nSession = new NotesSession();

            // open database
            nDatabase = nSession.getDatabaseByPath(serverName + "!!" + dbPath);
            nDatabase.open();

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

            // store them to note
            FileAccess.saveData(nNote, fileName, fileData.getBytes());

        } catch (NotesAPIException e) {
            e.printStackTrace();
        } finally {
            // recycle NAPI objects
            recycleNAPIObject(nNote, nDatabase, nSession);
        }
    }

    /**
     * converts an input stream to a string
     * 
     * @param is
     *            the input stream to convert
     * @return String
     */
    static String convertStreamToString(java.io.InputStream is) {
        java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\A");
        return s.hasNext() ? s.next() : "";
    }

    /**
     * recycleNAPIObject helper method for recycling NAPI objects
     * 
     * @param nObjects
     *            the NAPI objects to recycle
     */
    static void recycleNAPIObject(NotesObject... nObjects) {
        for (NotesObject nObject : nObjects) {
            if (nObject != null) {
                try {
                    (nObject).recycle();
                } catch (NotesAPIException ne) {
                }
            }
        }
    }
}

If the class looks like this…

…just hover one  of the entries and select “Fix project setup”.

Then, you can choose the missed bundle:

Build the project, and open one of the files by clicking a link in the Files.xsp. Here is an example for the file WEB-INF/faces-config.xml:

Now you can click the “Load” button to read the content of the file.

You can edit the file now and save it to the NSF.

If you got to package explorer (Hit F9 for refresh) you can see the changes:

XPages: WebContent Files (1) – Create a file using the Java NAPI

18. November 2014 Posted by Sven Hasselbach

Re: Re: 41. DNUG Konferenz: Track Entwicklung am 12.11.2014

13. November 2014 Posted by Roswitha Boldt

Als Antwort auf: Re: 41. DNUG Konferenz: Track Entwicklung am 12.11.2014

Gemeinsam mit meinem Team freue ich mich über dieses gute Feedback. Die positive Resonanz zu den Themen der beiden Techniktracks hatte sich schon bei der Vorauswahl der Sessions abgezeichnet.
Ein herzliches Dankeschön auch von unserer Seite an alle Referenten und Track Manager.