Search

Domino Upgrade

VersionSupport end
5.0
6.0
6.5
7.0
8.0
8.5
Upgrade to 9.x now!
(see the full Lotus lifcyle) To make your upgrade a success use the Upgrade Cheat Sheet.
Contemplating to replace Notes? You have to read this! (also available on Slideshare)

Languages

Other languages on request.

Twitter

Useful Tools

Get Firefox
Use OpenDNS
The support for Windows XP has come to an end . Time to consider an alternative to move on.

About Me

I am the "IBM Collaboration & Productivity Advisor" for IBM Asia Pacific. I'm based in Singapore.
Reach out to me via:
Follow notessensei on Twitter
(posts)
Skype
Sametime
IBM
Facebook
LinkedIn
XING
Amazon Store
Amazon Kindle
NotesSensei's Spreadshirt shop
profile for stwissel on Stack Exchange, a network of free, community-driven Q&A sites

26/07/2017

Static APEX code analysis with PMD

Category  

Coding standard are only as good as they are followed. One venerable tool to check source code is PMD. When you, like I did, wonder what acronym PMD represents, you will be disappointed. PMD supports the usual suspects like C, C++, C#, Fortran, Java, JavaScript, Go, Groovy, XML... as well as Apex and Visualforce.

The default ruleset for Apex contains 34 rules and are the ones also used by CodeClimate

PMD is a Java application and you have a number options to run it:

  • As a command line application
  • Using ANT or Maven
  • In your CI platform (using command line, ANT or Maven )
  • Linking your Github (or Gitlab, Bitbucket) repository to a service like CodeClimate

PMD supports a series of output formats like plain, csv, html (different flavours) and XML. When you understand XSLT, the XML format allows you to render whatever report you deem fit

21/07/2017

From Blogsphere to a Static Site (Part 5) - Comment front-end

Category

In Part 4 I described the comment backend. This installment sheds a light on the comment front-end.

Comments can be tricky. One lesson I learned early: When your comment form is standard HTML form, it attracts spam like a light bulb attracts moths. So the requirement were:

  • The original blog entry should not contain any HTML form. It should be loaded on a button click using JavaScript. Nota bene: this isn't hide/show, but actual manipulation of the DOM
  • The dynamic form shall not contain a POST URL, but submission should be in JavaScript - keeps a lot of the scumbags out already
  • Submission should be secured with a Captcha
  • Some formatting should be allowed. I opted for a Markdown editor with preview capabilities

The first component is the placeholder for the existing comments and the button showing the comment form:

<a name="comments"></a>
{{^commentsclosed}}
<div class="well well-raised" style="text-align : center">
  <button class="btn btn-lg btn-info" data-toggle="collapse" data-target="#commentform_{{UNID}}" type="button">
    Add your comment...  <span class="glyphicon glyphicon-comment"></span>
  </button>
</div>
<div id="commentform_{{UNID}}" class="collapse"></div>
{{/commentsclosed}}
<div class="well well-raised">
  <h4>Comments</h4>
  <ol id="commentList">
    {{#comments}}
    <li>
      {{#gravatarURL}}<img src="{{.}}" class="gravatarimg" /> {{/gravatarURL}} posted by <b>{{author}}</b> on <i>{{createdString}}</i>:
      <br /> {{& comment}}
      <hr style="clear : both" />
    </li> {{/comments}} {{^comments}}
    <li id="nocomments">
      <h5>No comments yet, be the first to comment</h5>
    </li>
    {{/comments}}
  </ol>
</div>

The second component is the comment form, implemented as mustache template - one of the reasons I picked Mustache: runs on the server and the client in tons of languages

<form title="Comment form for blog discussion" onSubmit="return addComment(this,'{{recaptchaid}}','{{parentId}}')" class="form-vertical well well-raised">
  <fieldset>
    <legend>Add your comment</legend>
    <p>Please note: <b>Comments without a valid and working eMail address will be removed.</b>
      <br /> This is my site, so I decide what stays here and what goes.</p>
     <div class="control-group" id="commentcontrol">
      <label class="control-label" for="Commentor">Name (required, published)</label>
      <div class="controls">
        <input class="input-xlarge focused" id="Commentor" size="30" accesskey="n" name="nameAuthor" />
      </div>
      <label class="control-label" for="Email">eMail (required, not published)</label>
      <div class="controls">
        <input type="eMail" class="input-xlarge focused" id="Email" size="30" accesskey="n" name="txtEmail" placeholder="A working eMail please!" />
      </div>
      <label class="control-label" for="webSite">URL (optional)</label>
      <div class="controls">
        <input type="url" class="input-xlarge" id="webSite" size="30" accesskey="n" name="txtWebSite" />
      </div>
      <div class="controls">
        <div id="wmd-panel" class="wmd-panel">
          <table style="width : 100%" border="0">
            <tr>
              <td style="width : 50%; vertical-align : top">
                <label class="control-label" for="wmd-input">Your Comment (Use markdown like <a href="//stackoverflow.com/editing-help" target="_blank">Stackoverflow</a>)</label>
                <div id="wmd-button-bar"></div>
                <textarea class="wmd-input" id="wmd-input" name="Body"></textarea>
              </td>
              <td style="width : 50%; vertical-align : top">
                <label class="control-label">Preview</label>
                <div id="wmd-preview" class="wmd-panel wmd-preview"></div>
              </td>
            </tr>
          </table>
        </div>
      </div>
      <div class="controls" id="captchadiv">Captcha here</div>
      <div class="form-actions">
        <button id="commentsubmit" type="submit" class="btn btn-primary btn-large">Post your comment</button>
      </div>
    </div>
    <div class="alert alert-block" id="alertContainer" style="display : none">One moment please, submitting comment...</div>
  </fieldset>
</form>

The whole mechanism gets to work with just a few jQuery JavaScript functions (Vanilla JS would work too, but I had JQuery already for the social buttons, so I reused that) and the respective JS files:

16/07/2017

Ownership flow of customer community created cases

Category

In a previous entry I mapped out sharing abilities the Salesforce platform is capable of.

In this entry I will put these capabilities to practial use. The scenario starts with a customer logging into the customer community and raising a ticket. Client representative, the partner and support staff need/want access to the case. The case needs to flow along the same processing as cases created by other means (call, email, IoT). The following diagram explains the flow (click for a larger version):

Customer Portal Created Cases Ownership flow

The diagram has been rendered using Websequencediagrams based on a plain text file:

14/07/2017

Using FontAwesome in your VisualForce pages

Category

I'm a big fan of Font Awesome (including backing Version 5). It allows to add icons without the overhead of loading tons of small graphic files. In a recent internal project I had to integrate FontAwesome into a Salesforce VisualForce page

Installing FontAwesome

In theory you could load the font from a CDN. However based on security settings this might or might not work. So I decided to add FontAwesome as resource to my project:

  1. Download FontAwesome 4. Or support the team and use Version 5
  2. Add the zip file as static resource to your setup:
    Static Resource for FontAwesome
  3. Make sure you have set the cache control to public, so the font doesn't need download after first use.

Adding to the VisualForce Page

The font gets added using a stylesheet that is included in the zip file added as a resource in the previous step. the apex:stylesheet element takes care of that. The only catch: the zip file is internally "expanded" OS/X style with the file name (sans extension) as directory name. So the tag needs to look like this:

  <apex:stylesheet value="{!URLFOR($Resource.fontawesome,'/font-awesome-4.7.0/css/font-awesome.css')}"/>

Using Icons

This follows the standard approach: you create an empty &lt;i&gt; element and use the class property to specify icon and options. Like this:

  <i style="color: red" class="fa fa-user-circle fa-2x" aria-hidden="true"></i>

Make sure you have a look at the full selection of icons available.

As usual: YMMV

10/07/2017

Salesforce Community License Overview

Category

To facilitate collaboration across corporate boundaries, Salesforce offers Salesforce Communities. The licence for communities come in three flavours: customer community, customer community plus and partner community. There are similarities and differences between the entitlements.

The biggest difference can be seen between customer community and customer community plus. There's a simple rationale behind it: a customer community account uses simplified sharing access, so the computational load to determine access of potentially millions of users stays reasonable and easy to grasp for administrators:

Community License Overview

All licences, full Salesforce or one of the community licence types, access the same data, in the confines of the entitlements. So it's NOT different products, just different permissions on the Salesforce platform.

07/07/2017

Sharing is caring - Salesforce edition

Category

I like declarative security to give access exactly to the extend a user requires. When learning Salesforce, I discovered to my delight the portfolio of possibilities to tailor access. With great powers, as we know, come great responsibilities. Learning the Salesforce lingo can be quite daunting. So here is my little overview:

Salesforce Sharing Terminology, click for full size
  • Access to data in Salesforce is based on two principles: everything is owner based and a generally restricted access can be extended for given conditions, but not limited. This single vector of access makes systems cleaner that the ability to add and remove privileges based on conditions. It avoids the need to resolve conflicts where condition 1 gives access, while condition 2 would remove it. These conflict solution rules are a security flaw in waiting (prime vector for human error). Nevertheless access in Salesforce need to be well planned (How much does any role need to see: give to little and you invite data duplicates, give too much and you increase leakage risks) - How to plan is another story for another time
  • Access has 3 element: access to objects (that would be access to classes in OO), access to records (instances of a class) and fields (properties of a class instance)
  • Computation starts from the organization wide settings, which are the most restrictive settings for a given organisation and then gets extended with various means (see image above)
  • There's a general distinction between internal access and access via a community. This reflects the need to be able to interact with customers, suppliers and partners in a controlled fashion
  • Owner based: I've seen this quite often: data exists, gets used, but nobody wants to own it, the owner has left or data gets inaccessible when the owner gets deleted. All this issues don't happen in Salesforce since no object data can exist that doesn't have an owner and owner transfer capability is baked into the platform (even rule based, but that's another story for another time)
  • Hierarchical: access rules know the role and reporting hierarchy. So access can be granted to a user and her entire reporting hierarchy including subordinates etc. Quite extensive possibilities worth exploring

As usual YMMV

Disclaimer

This site is in no way affiliated, endorsed, sanctioned, supported, nor enlightened by Lotus Software nor IBM Corporation. I may be an employee, but the opinions, theories, facts, etc. presented here are my own and are in now way given in any official capacity. In short, these are my words and this is my site, not IBM's - and don't even begin to think otherwise. (Disclaimer shamelessly plugged from Rocky Oliver)
© 2003 - 2017 Stephan H. Wissel - some rights reserved as listed here: Creative Commons License
Unless otherwise labeled by its originating author, the content found on this site is made available under the terms of an Attribution/NonCommercial/ShareAlike Creative Commons License, with the exception that no rights are granted -- since they are not mine to grant -- in any logo, graphic design, trademarks or trade names of any type. Code samples and code downloads on this site are, unless otherwise labeled, made available under an Apache 2.0 license. Other license models are available on written request and written confirmation.