Automatic Project Login Web Addon

I’ve noticed that in my experience, most users log into a single project.  Either because there’s only one project in the environment, or because the projects are specific to their department or function and it’s the only one they have access to.  With that, it’s always slightly annoyed me that a user has to login and then click to access the single project they have.

I’ve wanted to build a web addon for a long time that would automatically send a user to their project if they’ve only got access to one, but still present the normal project list to someone with access to many.  I’m not very good with the Web SDK and have only done some very basic stuff, but I finally had success with this project and was able to somewhat accomplish it.  It’s not perfect, and I think it could be a lot better, but I’d like to share it today because I’ve encountered a few other people who thought this feature would be useful.  Also, if you are familiar with the Web SDK and think you can improve upon it, by all means please do so and drop any feedback in the comments section!

I’ll try to go step by step so that this is not only a “here’s the addon”, but a tutorial of sorts with using the Web SDK.  Although I’ve done a few other Java Web SDK posts, they’re centered around using the Java components for stand alone apps, and not customizing Web functionality.  I don’t think I know enough to do a comprehensive post on the subject, so here I’ll just share what I learned in this exercise.

By the way, here’s the addon if you just want it and don’t care.

Setting Up Your Environment
The addon requires some Java code that must be compiled.  While some previous examples have used Eclipse, that’s actually overkill for this.  Here’s a much easier way to do it:

To compile the Java Class, you must first download the JDK: http://www.oracle.com/technetwork/java/javase/downloads/jdk-6u26-download-400750.html

Once installation is complete, the best thing to do is create a little batch file like this:

"C:Program FilesJavajdk1.6.0_26binjavac" -source 1.4 -target 1.4 -classpath "C:Program FilesCommon FilesMicroStrategyWebBeans.jar;C:Program FilesCommon FilesMicroStrategyWebObjects.jar;C:Program FilesCommon FilesMicroStrategyWebApp.jar;C:Program FilesCommon FilesMicroStrategyWebAppTransforms.jar;C:Program FilesCommon FilesMicroStrategyWebTransform.jar" -g SoloProjectLogin.java
pause

The pause is so that you can see if there are any compilation errors.  You may need to adjust the path to javac or the MicroStrategy JAR files if yours are installed in a different place.

Java
This does require some Java code to be able to check the project count and then insert an HTML tag that will trigger the redirect:

package com.custom.microstrategy;
import com.microstrategy.web.app.ProjectInformation;
import com.microstrategy.web.app.transforms.ProjectsTransform;
import java.util.*;
import com.microstrategy.web.beans.MarkupOutput;

public class SoloProjectLogin extends ProjectsTransform
{
public SoloProjectLogin()
{
super();
}

public boolean isSingleProject()
{
ArrayList bProjects = super.getProjectsList();
boolean result = false;
if (bProjects.size() == 1)
result = true;
return result;
}

public void renderRedirect(MarkupOutput out)
{
ArrayList projects = super.getProjectsList();
ProjectInformation projectInfo = (ProjectInformation)projects.get(0); //get the first project
out.append("<meta http-equiv="REFRESH" content="0;url=Main.aspx?evt=3010&src=Main.aspx.3010&Port=0&Project=" + projectInfo.getProjectDetails().getProjectName() + "&Server=YOURSERVER&loginReq=true">");
out.append("<h3>Loading Project: " + projectInfo.getProjectDetails().getProjectName() + ".  Please Wait.</h3>");
out.append("<br>If the project does not load, <a href=Main.aspx?evt=3010&src=Main.aspx.3010&Port=0&Project=" + projectInfo.getProjectDetails().getProjectName() + "&Server=YOURSERVER&loginReq=true>click here</a>.</br>");
out.append("<br><img src=/microstrategy/plugins/SoloProjectLogin/images/loader.gif></br>");
}
}

So what happens here is our add on will extend the ProjectsTransform which normally handles loading the projects.  The first function, isSingleProject I’ll use later, but it’s basically a flag that tells us if there is only 1 project, or if there are multiple projects returned.  It’s important to note that this is based on the user’s security, not the actual list of projects.  You may have 10 projects, but if the user only has access to 1, then this will return 1.

Next is where the actual redirect happens.  In order for this to work, there are two important pieces that are required:

  1. The function must be named renderWhatever .. in my case, renderRedirect.  It’s a requirement of the framework for later on when we call it.
  2. It must accept a parameter called MarkupOutput out which is how our html insert will be integrated with the web page output.
Effectively, this function adds a <meta> tag that will cause the browser to immediately redirect to a URL that we’ll provide to the project they have access to.  We’ll get the project name from the same list we used to determine how many projects they had access to in the first place.  Technically, a <meta> tag is supposed to be in the <head> tag at the top, but via this technique, it’ll end up in the <body>.  To make it worse, there will already be another <meta> tag in it’s proper place on the page.  Despite my utter disregard for html standards, this still works in the latest browsers that I tested with.  But just in case something goes wrong, I still provide a direct link for the user to click in the event the redirect does not work.
Can you do better?
Unfortunately, this is the best manner of redirect I could come up with, since I need to load the project page in order to find out how many projects they have access to.  I’d love to handle this outside of the project page so that the project is the first page loaded.  As it stands, it takes some amount of time to actually log into the project, so the user will see the project page for ~ 1 second which may be disorienting.  The best I could do to combat this was to add a loading gif and a message that a redirection was taking place.  If you have a method of doing this much more quietly, I’d love to hear about it!
Project Layout XML
The next file is the ProjectLayout.xml file which tells MicroStrategy how to render the Project page.  This is where we’ll inject our logic for how to handle the single project scenario.
This page is XML, but it uses MicroStrategy’s framework for laying out the page intelligently.  It reads like a programming language, even though it’s in an XML format.
For example, if you open the file, the first few lines you see will look like this:
<mstrlayout:if name="areThereProjectsToDisplay">
    <mstrlayout:then>

Those are XML nodes, but they are making calls to the ProjectsTransform java class to invoke a boolean function to return whether or not the user has access to projects.  If true, then it goes on and lists the projects, and it false, you get the familiar “There are no projects loaded on this web server” message.

For our add on, we’ll add to this condition, like so:

<mstrlayout:if name="areThereProjectsToDisplay">
    <mstrlayout:then>
            <mstrlayout:if name="isSingleProject">
<mstrlayout:then>
<mstrlayout:render name="Redirect"/>
</mstrlayout:then>
<mstrlayout:else>

These calls will be sent to our add on, and you’ll notice the two functions that we’ve defined: isSingleProject and renderRedirect.  First, our isSingleProject function will return a true or false.  If it’s false, then the ProjectLayout will continue on it’s normal path and continue to render the project list so the user can choose which project they want to go to.  But if it’s true, then it’ll call our renderRedirect function and add our <meta> tag to redirect the user automatically.  You’ll notice the curious syntax to call the renderRedirect function, in that the name is actually only “Redirect”.  This seems to be the convention for calling a render function and why the function requires the render prefix.  Also note that I haven’t declared any MarkupOutput out parameter that my java function is expecting.  This too occurs automatically, and that is what makes those two requirements I mentioned earlier necessary.  The good news is that this is really easy to implement, as you’ve seen it’s only a few lines of basic code to accomplish.

One last modification to this file is to close out the open if / else tags at the bottom of the file, around this section:

           <mstrlayout:render name="messagesSection"/>
</mstrlayout:else>
</mstrlayout:if>

</mstrlayout:then>

Adding our Add On to the Style Catalog
Finally, we just need to modify the StyleCatalog.xml file to tell it to use our customized ProjectsTransform instead of the default one.  The full plugin file will look like this:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE StyleCatalog SYSTEM "styleCatalog.dtd">
<StyleCatalog description="MSTR System Style Catalog" name="MSTRStyleCatalog" version="1.1">
<TransformDefns>
<TransformDefn class="com.custom.microstrategy.SoloProjectLogin" name="SoloProjectLogin"/> </TransformDefns>
<Styles>
   <Style description="Style: Display HTML for the projects that are currently available on the servers" name="ProjectsStyle" transform="SoloProjectLogin">
      <ActualParameters>
        <ActualParameter name="displayFlag" type="2" value="15"/>
        <ActualParameter name="useStyleSorting" type="4" value="false"/>
      </ActualParameters>
      <Layouts>
        <Layout layout_source="AppLayoutSourceFile" order="1"><![CDATA[/plugins/SoloProjectLogin/WEB-INF/xml/layouts/ProjectsLayout.xml]]></Layout>
      </Layouts>
    </Style>
</Styles>
</StyleCatalog>

You can download a copy of the plugin here, but you need to edit the java file to put in your IServer name, then recompile it with compile.bat.

The plugin will look something like this on the Project page:

You may also like...