Category Archives: Programming Notes

Access Portlet Session as Anonymous User In WebSphere Portal

By default, WebSphere Portal does not enable session tracking for anonymous users, hence the following request.getPortletSession() code snippet will always return null for anonymous users:

private static SideNavigationPortletSessionBean getSessionBean(PortletRequest request) {
 PortletSession session = request.getPortletSession();
 if (session == null)
 return null; // <-- will always return null for anonymous users
 SideNavigationPortletSessionBean sessionBean = (SideNavigationPortletSessionBean) session.getAttribute(SESSION_BEAN);
 if (sessionBean == null) {
  sessionBean = new SideNavigationPortletSessionBean();
  session.setAttribute(SESSION_BEAN, sessionBean);
 }
 return sessionBean;
}

And this set the team wondering on how out of the box IBM portlets like Sitemap portlet (PA_SearchSitemapPort.ear) transports information to the presentation layers (JSP)? Hence we de-compiled the sitemap.jar and found out that they are transporting the information through the render parameters which is something that matches the paragraph found in Accessing the portlet session on the anonymous page:

If you need to enable session tracking across requests for non-authenticated users, you can do so by setting the public.session parameter in the portal Navigator service configuration or by setting the com.ibm.portal.public.session container run time option in a JSR 286 portlet deployment descriptor. Note that this may result in significantly increased memory consumption. … Instead of using these options, portlets that need to maintain interaction state even for non-authenticated users should use render parameters to keep this information instead of the portlet session, as recommended by the Java Portlet Specification.

 

Below is an example on how to pass information using render parameters?

  1. Under doView method, set the information to RenderRequest’s parameters
    public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException {
     // ...
    
     request.setAttribute("rootPage", rootPage);
    
     // Invoke the JSP to render
     PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(JSP_FOLDER + VIEW_JSP);
     rd.include(request, response);
    }
  2. At JSP, retrieve the information as follows:
    <jsp:useBean id="rootElement" class="sg.xxx.xxx.sidenavigation.model.PageElement" scope="request"/>
    <%
     PageElement rootPage = (PageElement)request.getAttribute("rootPage");
     if (rootPage != null) {
      // logic ...
     }
    %>
    

How to Merge PDF Files with PDFBox in Java?

Merging PDF files in java is made easier with Apache PDFBox.

The codes below illustrate how to sort and merge all PDF files found in a particular directory according by their last modified date:

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;

import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.util.PDFMergerUtility;

public class test {
 public static void main(String[] args) throws IOException, COSVisitorException {
  int maxPdf = 1000; // use this to troubleshoot java/lang/OutOfMemoryError exception
  String pdfDirPath = "C:\\circulars_and_notices\\pdfs\\port_marine_notices";

  File pdfDir = new File(pdfDirPath);
  if (pdfDir.isDirectory()) {
   // proceed to crawl thru the folder and merge the pdf according to last mod date
   File[] pdfs = pdfDir.listFiles();
   int cnt = pdfs.length;

   if (cnt > 0) {
    // sort the pdfs by last mod date in desc order
    Arrays.sort(pdfs, new Comparator() {
    public int compare(File f1, File f2) {
     return Long.compare(f2.lastModified(), f1.lastModified());
     }
    });

    if (maxPdf != 0 && maxPdf < cnt) {
     cnt = maxPdf;
    }

    // start add merging sources
    PDFMergerUtility pdfMerger = new PDFMergerUtility();

    // set destination
    pdfMerger.setDestinationFileName("C:\\mergeDocs.pdf");

    // add in pdf source
    for (int i = 0; i < cnt; i++) {
     File file = pdfs[i];
     pdfMerger.addSource(file);
    }

    // merge pdfs
    pdfMerger.mergeDocuments();

   } else {
    System.out.println("Target directory is empty.");
   }
  } else {
   System.out.println("Target is not a directory (" + pdfDirPath + ").");
  }
 }
}

The codes above should works fine in most scenarios. But if you are merging large PDFs files like in my case, then the chances of encountering “java/lang/OutOfMemoryError” exception is high. Of course a quick solution is to increase heap size but this will only be a temporary solution.

Lucky for us, PDFBox offers another alternative way of merging PDFs by storing the PDF streams into a temp file. See below code for illustrations:

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.io.RandomAccessFile;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLink;
import org.apache.pdfbox.util.PDFMergerUtility;

public class test {
 public static void main(String[] args) throws IOException, COSVisitorException {
  int maxPdf = 1500; // use this to troubleshoot java/lang/OutOfMemoryError exception
  String pdfDirPath = "C:\\circulars_and_notices\\pdfs\\port_marine_notices";

  File pdfDir = new File(pdfDirPath);
  if (pdfDir.isDirectory()) {
   Date startTime = new Date();
   System.out.println("Start time: " + startTime.toString());

   // proceed to crawl thru the folder and merge the pdf according to last mod date
   File[] pdfs = pdfDir.listFiles();
   int cnt = pdfs.length;

   if (cnt > 0) {
    // sort the pdfs by last mod date in desc order
    Arrays.sort(pdfs, new Comparator<File>() {
     public int compare(File f1, File f2) {
      return Long.compare(f2.lastModified(), f1.lastModified());
     }
    });

    if (maxPdf != 0 && maxPdf < cnt) {
     cnt = maxPdf;
    }

    // create a temp file for temp pdf stream storage
    String tempFileName = (new Date()).getTime() + "_temp";
    File tempFile = new File("C:\\" + tempFileName);

    // proceed to merge
    PDDocument desPDDoc = null;
    PDFMergerUtility pdfMerger = new PDFMergerUtility();
    try {
     // traverse the files
     boolean hasCloneFirstDoc = false;
     for (int i = 0; i < cnt; i++) {
      File file = pdfs[i];
      PDDocument doc = null;
      try {
       if (hasCloneFirstDoc) {
        doc = PDDocument.load(file);
        pdfMerger.appendDocument(desPDDoc, doc);
       } else {
        desPDDoc = PDDocument.load(file, new RandomAccessFile(tempFile, "rw"));
        hasCloneFirstDoc = true;
       }
      } catch (IOException ioe) {
       System.out.println("Invalid PDF detected: " + file.getName());
       ioe.printStackTrace();
      } finally {
       if (doc != null) {
        doc.close();
       }
      }
     }

     System.out.println("Merging and saving the PDF to its destination");
     desPDDoc.save("C:\\mergeDoc.pdf");

     Date endTime = new Date();
     System.out.println("Process Completed: " + endTime);
     long timeTakenInSec = endTime.getTime() - startTime.getTime();
     System.out.println("Time taken: " + (timeTakenInSec / 1000) + " secs " + (timeTakenInSec % 1000) + " ms");

    } catch (IOException | COSVisitorException e) {
     e.printStackTrace(); // will encounter issues if it is more than 850 pdfs!!
    } finally {
     try {
      if (desPDDoc != null) {
       desPDDoc.close();
      }
     } catch (IOException ioe) {
      ioe.printStackTrace();
     }
     tempFile.delete();
    }
   } else {
    System.out.println("Target directory is empty.");
   }
  } else {
   System.out.println("Target is not a directory (" + pdfDirPath + ").");
  }
 }
}

[21/4/2014] We have encountered org.apache.pdfbox.exceptions.COSVisitorException: java.lang.NullPointerException when we tried to merge large number of PDFs (<850 pdfs) at once. Hence we decided to revise our codes by merge our PDFs in smaller quantities before merging them as one.

How to Access SharePoint Web Services via Javascript?

Been tasked by my boss with another tight deadline project (understand client’s requirement and developed 2 mobile app within 1 month). Both of the apps required to read data from SharePoint Web Services using Javascript.

Before we proceed, it is important to know what are the types of SharePoint web services that are available to us? Click here for a list of SharePoint services.

Next, we need to understand how to read and call web services’ methods. In the example below, we will demonstrate how we derived and constructed our SOAP message to retrieve list’s items (API: List.GetListItems method):

  1. Always wrapped our SOAP message block with the following header and footer:
    Header

    <soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>
     <soapenv:Header/>
     <soapenv:Body xmlns='http://schemas.microsoft.com/sharepoint/soap/'>
    

    Footer

     </soapenv:Body>
    </soapenv:Envelope>
    
  2. Construct the web service’s method and parameters exactly as shown in MSDN. In our example, we will input listName and sort the result according to the title:
    <GetListItems>
     <listName>{A4E4AA50-CB01-48C4-9D24-DD6404CD70C1}</listName>
     <query>
      <Query>
       <OrderBy>
        <FieldRef Ascending='TRUE' Name='Title'/>
       </OrderBy>
      </Query>
     </query>
    </GetListItems>
    

Lastly wrapped the SOAP message that you form above and sent it thru using jQuery.ajax method (example like the one below):

$.ajax({
 type: "POST",
 url: url /* the url will be as stated in MSDN Web Reference, for all list related services, it will be http://<Site>/_vti_bin/Lists.asmx*/,
 data: q.join("") /* the soap message that we have construct earlier*/,
 contentType: "text/xml; charset=utf-8",
 dataType: "html" /* can be xml */,
 success: function(xdata){
  result.css("color","green").html($('<div/>').text(xdata).html());
 },
 error: function(a,b,c){
  result.css("color","red").html("Unable to connect ("+c+").");
 }
});

WebSphere Portal: AuthorizationException Is Thrown While Calling Workspace getById Method

Below looks like an innocent block of codes written to retrieve WCM items:

 Content content = null;
 Workspace ws=WCM_API.getRepository().getWorkspace();
 DocumentIdIterator iter = ws.findByPath(path, Workspace.WORKFLOWSTATUS_ALL);

 if(iter.hasNext()) {
  DocumentId docId = iter.nextId();
  if (docId.isOfType(DocumentTypes.Content)) {
   content = (Content)ws.getById(docId,true,true);
  }
 }

But as soon as you try to retrieve WCM items with “User” access, the following “AuthorizationException” will be thrown (even though you are able to view the items in WCM Authoring Portlet):

  • com.aptrix.pluto.security.AuthorizationException
  • com.ibm.workplace.wcm.api.exceptions.AuthorizationException

This is because getById method by default required min “Contributor” rights. In order to resolve the issue, call Workspace.useUserAccess(true) before you call the getById method.

WebSphere Portal: Customize Authoring Template’s Elements With JSP

WebSphere Portal allows you to customize some of the Authoring Template’s elements look-and-feel using “Custom JSP” field and with some creativity, we can fulfil or further enhance our client’s WCM experience.

Naming a few requirements that we have encountered so far:

  • “Are you able to display the email’s WCM url in the Authoring Template (refers to the email that is send by WCM Workflow Email Action)?”
  • “Can we have a Color picker function like the JSColor (http://jscolor.com) for our sliding banners?”
  • “Can we have a dynamic product list where we can sort using drag and drop action?”
  • and so on…

Before we start, we need to decide where to store the custom jsp. There are currently 2 ways to call (reference) the custom jsp:

  • Method 1: We can store the jsp within PA_WCM_Authoring_UI and PA_WCMLRingPortJSR286 application folders. Then we reference the custom jsp by /jsp/html/xxx.jsp. PA_WCM_Authoring_UI and PA_WCMLRingPortJSR286 can be found at <wp_profile>\installedApps\<cell> (example: C:\IBM\WebSphere\wp_profile\installedApps\WPS80Cell).
  • Method 2 (Our Preferred Method): Create a web application to store the jsp and install the application via IBM Application Server console as “WebSphere enterprise applications”. Reference the jsp thru the context path as shown: contextPath;<jsp path> (example: “/MyCustomJSPs;/jsp/xxx.jsp“).This method is easier to maintain and less prone to cumulative fix patches.

Steps to create your own web application container using RAD 9.0:

  1. Create a new Web Project (File > New > Project > Web Project).
  2. Select “Basic” Project Templates and “Java EE” as programming model. Click on the “Next” button.
  3. Select “Web Module” and click on the “Finish” button.

What do you need to know?

In order to fully replicate existing Authoring Template’s behaviour (Read, Edit and Render modes), usually we would create at least 2 custom jsp (for Read and Edit modes). In some rare cases, we usually do not need Render mode to further “massage” the values in Presentation Template.

Below is a draggable Multiple Links example that we have created for one of our clients (I have omit out some of the codes to prevent the post from been draggy):

Step 1: Create AT-MultipleLinks_EditMode.jsp for Edit Mode

<%@ page import="com.ibm.workplace.wcm.api.authoring.CustomItemBean"%>
<%
 String ENTRY_DELIM = "\\<\\<\\<entry\\>\\>\\>";
 String VALUE_DELIM = "\\<\\<\\<delim\\>\\>\\>";

 CustomItemBean customItem = (CustomItemBean) request.getAttribute("CustomItemBean");
 String fieldName = customItem.getFieldName();
%>
<div class='<%=fieldName%>_related_links'><%
 String value = (String) customItem.getFieldValue();
 if(!value.equals("")){
  // render existing values
  String[] entries = value.split(ENTRY_DELIM);
  for (int i=0,len=entries.length;i<len;i++){
   String[] info = entries[i].split(VALUE_DELIM);
   if(info.length==2){%>
    <div class="entry">
     <div class="row">
      <div class="lbl">Description:</div>
      <div class="txt"><input type="text" class="lotusText" value="<%= info[0]%>" size="80" /></div>
     </div>
     <div class="row">
      <div class="lbl">Url:</div>
      <div class="txt"><input type="text" class="lotusText" value="<%= info[1]%>" size="80" /></div>
     </div>
     <div class="row">
      <div class="lbl"></div>
     </div>
    </div>
 <% }
  }
 }

 // set the javascript method to call when users clicks on the save button
 customItem.setSubmitFunctionName(fieldName+"_submit");
%>
</div>

// ... codes been omit out

<script>
<!-- submit method to collect the links' values and insert them to the hidden field
function <%=fieldName%>_submit(){
 var values = new Array();
 $(".<%=fieldName%>_related_links").find(".entry").each(function(){
  var info = $(this).find(".lotusText");
  if(info.length==2){
   var desc = info.get(0).value;
   var url = info.get(1).value;
   values.push(desc+"<%=VALUE_DELIM%>"+url);
  }
 });
 $("#<%=fieldName%>").val(values.join("<%=ENTRY_DELIM%>"));
}
</script>

Step 2: Create AT-MultipleLinks_ReadMode.jsp for Read Mode.
The read mode custom jsp is almost the same as edit mode except that it should only contains codes that are sufficient for reading purpose.

<%@ page import="com.ibm.workplace.wcm.api.authoring.CustomItemBean"%>
<%
 String ENTRY_DELIM = "\\<\\<\\<entry\\>\\>\\>";
 String VALUE_DELIM = "\\<\\<\\<delim\\>\\>\\>";

 CustomItemBean customItem = (CustomItemBean) request.getAttribute("CustomItemBean");
 String fieldName = customItem.getFieldName();
%>
<div class='<%=fieldName%>_related_links'><%
 String value = (String) customItem.getFieldValue();
 if(!value.equals("")){
  // render existing values
  String[] entries = value.split(ENTRY_DELIM);
  for (int i=0,len=entries.length;i<len;i++){
   String[] info = entries[i].split(VALUE_DELIM);
   if(info.length==2){%>
    <div class="entry">
     <div class="row">
      <div class="lbl">Description:</div>
      // noticed the readonly attribute?
      <div class="txt"><input type="text" class="lotusText" value="<%= info[0]%>" size="80" readonly /></div>
     </div>
     <div class="row">
      <div class="lbl">Url:</div>
      // noticed the readonly attribute?
      <div class="txt"><input type="text" class="lotusText" value="<%= info[1]%>" size="80" readonly /></div>
     </div>
     <div class="row">
      <div class="lbl"></div>
     </div>
    </div>
 <% }
  }
 }
%></div>

Step 3: Add in a Text element in Authoring Template and set the Custom JSP path

readMode=/wps/PA_WCM_Authoring_UI;/jsp/html/customJSP/AT-MultipleLinks_ReadMode.jsp,editMode=/wps/PA_WCM_Authoring_UI;/jsp/html/customJSP/AT-MultipleLinks_EditMode.jsp

Step 4: Create AT-MultipleLinks_RenderMode.jsp to render the result

After you have successfully create the render jsp, create a WCM JSP Component and point it to the render jsp. Call the JSP component that you have just created in the presentation template.

<%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ page import="com.ibm.workplace.wcm.api.*, java.util.ArrayList, javax.portlet.*"%>
<%
 String ENTRY_DELIM = "\\<\\<\\<entry\\>\\>\\>";
 String VALUE_DELIM = "\\<\\<\\<delim\\>\\>\\>";
 String I_WAN_TO_COMPONENT = "I Want To";

 Content content = null;
 RenderingContext renderingContext = (RenderingContext) request.getAttribute(Workspace.WCM_RENDERINGCONTEXT_KEY);
 if (renderingContext == null) {
  Object portletRequest = request.getAttribute("javax.portlet.request");
  if (portletRequest != null && portletRequest instanceof PortletRequest) {
   // JSR286 rendering
   renderingContext = (RenderingContext) ((PortletRequest) portletRequest).getAttribute(Workspace.WCM_RENDERINGCONTEXT_KEY);
  }
 }
 if (renderingContext != null) {
  content = renderingContext.getContent();
 }

 if (content != null && content.hasComponent(I_WAN_TO_COMPONENT)) {
  ContentComponent cmpt=content.getComponentByReference(I_WAN_TO_COMPONENT);
  if (cmpt instanceof TextComponent) {
   String iWantToLinks = ((TextComponent) cmpt).getText();

   if(!iWantToLinks.equals("")){
    out.print("<div class='i_want_to'><div class='title'>I Want To....</div><ul>");
    String[] entries = iWantToLinks.split(ENTRY_DELIM);
    for (int i=0,len=entries.length;i<len;i++){
     String[] info = entries[i].split(VALUE_DELIM);
     if(info.length==2){%>
      <li><a href='<%=info[1]%>'><%=info[0]%></a></li>
     <%}
    }
    out.print("</ul></div>");
   }
  }
 }
%>

 

More Examples:

WebSphere Portal: How to get HttpServletRequest and HttpServletResponse from Portlet Request?

Like most portlet developments, there are some scenarios where you might need to retrieve HttpServletRequest and HttpServletResponse from Portlet Request (RenderRequest/RenderResponse/ActionRequest/ActionResponse etc).

In WebSphere Portal, there is a PortletUtils utility class that provides the method you need:

import com.ibm.ws.portletcontainer.portlet.PortletUtils;

// call the respective methods to get HttpServletRequest/HttpServletResponse you need
PortletUtils.getHttpServletRequest(request);

[10/9/2014]: As highlighted by Stefan Schmitt, the above mentioned method is not supported by IBM. We found out about this class when we de-compiled “Sitemap” portlet. There is 7 or more PortletUtils types if you viewed it from your RAD “Quick fix”, use it at your own discretion.

WebSphere Portal: Theme Development Useful References

WebSphere Portal API

WebSphere Portal Library Tags | link
Our trusty library tags since WebSphere Portal 6.0 (maybe earlier)!
(The tags mentioned are only for use in theme and skin JSPs. Do not use portal tags in portlet JSPs.)

  • <portal-core/> tags – Used to provide portal core functionality such as entering the main render flow as well as URL-related aspects of the page.
  • <portal-dynamicui/> tags – Used to enable dynamic user interface features such as closing dynamic portlets and pages.
  • <portal-fmt/> tags – Used to provide enhanced portal formatting capabilities.
  • <portal-logic/> tags – Used to provide conditional logic.
  • <portal-navigation/> tags – Used to implement navigation tasks such as generating URLs and traversing the portal navigation model.
  • <portal-showtools/> tags – Used to provide administrative tools on the theme and skin level.
  • <portal-skin/> tags – Used to build a portlet title bar as well as make various functional icons available in the title bar.
  • <portal-theme-ext/> tags – Used to provide extended functionality to enhance the portal themes.

WebSphere Portal EL Beans | link
Since WebSphere Portal 7.0, Expression Language (EL) beans has been added for easy access to WebSphere Programming models. The beans are accessed in the global wp namespace. For more information on specific models, refer to the Portal 8.5 SPI Javadoc external link. Examples of the common used beans:

  • ${wp.metadata[node]}
  • ${wp.node.contentNode}
  • ${wp.identification[node]}
  • ${wp.node.metadata[‘metaDataKey’]}
  • ${wp.navigationModel}

Missing from the documentation:

  • “INTERNALURL” is missing from ContentNodeBean.contentNodeType documentation.

WebSphere Portal EL Available Variables (WebSphere Portal 8.0)
Do remember to check out bootstrap.jspf before init your variables, as some of the useful variables have already been initialized by the jsp fragment. Examples:

  • ${pageTitle} – current page’s title
  • ${currentNavNode} – current page’s navigation node
  •  ${aggMD} – an aggregated metadata of the current page
  • ${deviceClass} – device class, values available [<empty string>/tablet/smartphone]

Setting Dynamic Content Spot Mapping with mvc:URI | link
The mvc:URI scheme is a special URI format that accesses different resources, depending on the device class. This scheme is used by the Portal 8001 theme in the definition of several dynamic content spots. Example of possible combinations:

  • mvc:res:/hello.jsp: Uses a single default URI.
  • mvc:res:/hello.jsp,smartphone@res:/hello_smartphone.jsp: Uses res:/hello.jsp as the default URI and res:/hello_smartphone.jsp as the URI for smartphones.
  • mvc:res:/hello.jsp,smartphone/tablet@res:/hello_mobile.jsp: Uses res:/hello.jsp as the default URI and res:/hello_mobile.jsp as the URI for smartphones and tablets.
  • mvc:res:/hello.jsp,smartphone@,tablet@res:/hello_tablet.jsp: Uses res:/hello.jsp as the default URI and res:/hello_tablet.jsp as the URI for tablets. No URI is assigned for smartphones.

Lucene IOException: Too many open files

My client just alerted me that Lucene is throwing IOException that reads “Too many open files”. Took me quite a while to troubleshoot as I am not familiar with Linux commands, anyway below are some of the recommendations and how to troubleshoot the issues in Linux:

If you are encountering the exception:

  1. Ensure that you have explicitly close all file handles that you have open using a try/catch/finally block (always remember to close them in the finally block).
  2. Do not set IndexWriter’s mergeFactor to large values. Large values speed up indexing but it will also increase the number of files needed to be opened simultaneously.
  3. It is advised in the API to share a single IndexSearcher across multiple searches instead of creating a new one per-search.
  4. Increase the number of files that can be opened simultaneously (ulimit).

Steps to monitor unclosed Lucene file handlers (IndexReader in particular):

  1. Key in “ps -ef” (to identify out the process id)
  2. Key in “ls -l /proc/<process id>/fd | wc -l” (this will return the numbers of files that are opened)
  3. Visit one of the pages that use Lucene search feature, repeat hit the feature and monitor the files count (by keying the command in point #2).
  4. If there is an increment increase in the number of open files, this might means that you might forget to close the IndexReader.
  5. In order to confirm your suspicious, type “pfiles <process id> > 1” to output the result to a file.
  6. Type “more 1” to read, you should be able to see traces of Lucene index files opened (else you should be safe).
  7. Once you have resolved this issue, move on to the next page.

References:

  1. LuceneFAQ – Why am I getting an IOException that says “Too many open files”?

How To Read InputStream To A String?

This method will comes in handy when we need to convert input stream to string.

With reference to http://stackoverflow.com/questions/309424/read-convert-an-inputstream-to-a-string and yes, Pavel Repin’s answer should be the official answer for that particular thread.
(just cant seems to vote his answer up)

    public static String convertStreamToString(java.io.InputStream is) {
        java.util.Scanner s = new java.util.Scanner(is, "UTF-8").useDelimiter("\\A");
        return s.hasNext() ? s.next() : "";
    }

MySQL: Check the manual that corresponds to your MySQL server version for the right syntax to use near ‘OPTION SQL_SELECT_LIMIT=100’ at line 1

Scenario:
This is the first time you are exactly calling that particular MySQL database and you are getting the following error message from your database client or IDE:

"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'OPTION SQL_SELECT_LIMIT=100' at line 1"

Solution:
If so, you are in luck as the issue can be as simple as updating your MySQL jar. Yup most likely your jar is outdated.
Click here to update your jar now.