Return to Jive Software

Jivespace Community Blog

8 Posts tagged with the customization tag

Attention, Developers!

 

Have you ever wondered how you can run an upgrade task in a plugin to do something like add an extra column to a table or a new index to boost performance?  You know, those one-time tasks that need to be applied consistently across all your environments?  One of the powerful (yet often overlooked) features in Jive SBS 3.0 is the ability to run upgrade tasks in a plugin.  These tasks are run once and can do anything from modifying a database to creating new files and folders.

 

The Past...

 

Prior to SBS, developers relied on a number of techniques to perform upgrade tasks, including:

 

  • Checking for the presence of a system property and, if not present, firing off a background thread to perform the upgrade task from the plugin class' init() method
    (downside: someone deletes the system property and your upgrade task gets run again, clustering introduces risk that your upgrade will be run more than once, more work than necessary)
  • Writing a SQL script that could be run by the DBA on each environment prior to the plugin upgrade
    (downside: may require special permission to run scripts, especially in hosted environment; not cross-platform compatible; multiple steps in deployment process may easily be forgotten)
  • Overlaying the core application to include upgrade tasks with core application upgrade tasks to take advantage of native process for handling upgrades
    (downside: must be merged with every release, requires multiple deployment artifacts, risky)

 

...And Now?

 

I hoped you would ask!  Here's what you need to do:

 

Step 1

 

If you don't already have it, add the following two items to your plugin.xml:

 

<plugin>
     <!--...omitted for clarity...-->
     <databaseKey>pluginName</databaseKey>
     <databaseVersion>1000001</databaseVersion>
     <!--...omitted for clarity...-->

</plugin>

 

Now when the plugin is installed, it will create a record in the jiveVersion database table with the appropriate values for name and version.

 

 

Step 2

 

Create a new file "upgrade.xml" at the root of your plugin.  This new file will live alongside your spring.xml, struts.xml, etc., and contains the list of upgrade tasks that will be run.  Each upgrade task is given a version.  If the version of your upgrade task is greater than the value in the jiveVersion table for your plugin, your task will be run.  Once the upgrade is complete, the version in the database will be the same as the highest upgrade task version.  Here's an example upgrade.xml taken from our Supportal:

 

<upgrade-config>
    <upgrades>
        <upgrade order="1">
            <name>supportal</name>
            <tasks>
                 <!-- 3.2.0 -->
                <task version="32000001"
                    className="com.jivesoftware.community.upgrade.tasks.AddEnvironmentsTask"/>

                <task version="32000002"
                    className="com.jivesoftware.community.upgrade.tasks.EnvironmentPermissionsTask"/>


                <!-- 3.2.1 -->
                <task version="32100001"
                    className="com.jivesoftware.community.upgrade.tasks.DeleteDuplicateEnvironmentFieldValuesTask"/>


                <!-- 3.2.2 -->
                <task version="32200001"
                    className="com.jivesoftware.community.upgrade.tasks.RemoveWebServerRequirementFromEnvironmentsTask"/>


                <!-- 3.2.3 -->

                <task version="32300001"
                    className="com.jivesoftware.community.upgrade.tasks.UpdateEnvironmentFieldOptionsTask1"/>

            </tasks>
        </upgrade>
    </upgrades>
</upgrade-config>

 

Once you have added your task, make sure to update the databaseVersion in your plugin.xml to the same value as your highest upgrade task!

 

 

Step 3

 

Create your upgrade task class.  In the example below we're calling out to an XML file that contains the new schema details.  More on that in a sec.  Here's the source code:

 

package com.jivesoftware.community.upgrade.tasks;

...imports omitted

public class RemoveWebServerRequirementFromEnvironmentsTask implements UpgradeTask {

    private static final String SQL = "RemoveWebServerRequirementFromEnvironmentsTask";

    public String getName() {
        return "Remove requirement for filling out web server from environment template fields";
    }

    public String getDescription() {
        return "Task to mark environment template fields for web server as non-required.";
    }

    public String getEstimatedRunTime() {
        return "1 second";
    }

    public String getInstructions() {
        return "To run manually, copy the SQL from the RemoveWebServerRequirementFromEnvironmentsTask.xml and run directly against your DB.";
    }

    public boolean isBackgroundTask() {
        return false;
    }

    public void doTask() throws Exception {
       UpgradeUtils.executeSQLGenFile(SQL, getClass());
    }

}

 

 

Step 4 (almost there!)

 

The last thing you need to do (assuming you are updating your DB, of course) is to create the XML file that will be read when UpgradeUtils.executeSQLGenFile(SQL, getClass()) is called.  To do this create an XML file in the same path of your class with the same name as your class, only ending with the .xml extension.  Following the example above, this could look like the following:

 

<schema name="Environment Schema">

    <sql description="Update default data for environments."><![CDATA[
        update supenvtemplfield set isRequired = 0 where envtemplfieldid = 40;
        update supenvtemplfield set isRequired = 0 where envtemplfieldid = 59;
        update supenvtemplfield set isRequired = 0 where envtemplfieldid = 78;
        update supenvtemplfield set isRequired = 0 where envtemplfieldid = 97;
        update supenvtemplfield set isRequired = 0 where envtemplfieldid = 116;
        update supenvtemplfield set isRequired = 0 where envtemplfieldid = 135;
        update supenvtemplfield set isRequired = 0 where envtemplfieldid = 154;
        ]]>
    </sql>

</schema>

 

 

The <sql> element lets you execute arbitrary DML or DDL statements against your DB.  You can also use the <alter> tag to change an existing table:

 

    <alter table="jiveBlog" type="add" description="Add Container Type and ID to JiveBlog">
        <column name="containerType" type="int" nullable="false" default="-2"
                description="The type of the container to which the blog belongs"/>

        <column name="containerID" type="bigint" nullable="false" default="17"
                description="The ID of the container to which the blog belongs."/>

        <index type="normal" name="jiveBlg_ctID_idx" column="containerID, containerType"/>
    </alter>

 

Additionally, you can define new tables using the same syntax as you would in your schema.xml:

 

    <table name="environmentTemplate" description="Customer environment template">
        <column name="templateID" type="bigint" nullable="false" description="Environment template ID."/>
        <column name="name" type="varchar" size="255" nullable="false" unicode="true"
                        description="The display name of the template (shows in environment template selection)."/>

        <column name="description" type="text" nullable="true" index_none="true" unicode="true"
                description="Tells admins the purpose of this template"/>

        <column name="status" type="int" nullable="false"
                description="The published status of the environment template."/>


        <index type="primary" name="envTempl_pk" column="templateID"/>
        <index type="normal" name="envTempl_templID_st_idx" column="templateID,status"/>
    </table>

 

 

What happens if my upgrade runs into problems?

 

It is important to note that plugin upgrades are run in the background during plugin initialization, so you won't see the upgrade screen similar to what is shown when you upgrade SBS.  However, any errors that occur during the plugin installation will be reported to you in the admin console under System > Plugins.  Here's what you can expect to see:

 

pluginError.GIF

 

Questions?

 

Leave a comment for me here, or shoot a message to @austrum on Twitter!

1,291 Views 1 Comments Permalink Tags: plugin, customization, upgrade, sbs

Out with the old

 

old_open_cases_widget.png

 

In the past, when a customer wanted to check on the status of any of their open cases they would log into their secure space overview page and use the Community Open Cases widget. This widget was designed with a very simple goal in mind, just display the open cases with a bit of extra information and an emphasis on Severity 1 issues. This proved useful for quite some time and gave customers a good overview of what was going on with their community from a support perspective.

 

However, there was one major flaw. Customers had no way of interacting with this information and often found it very difficult to organize this data in a manner that they could use quickly and efficiently. Welcome, open cases widget 2.0!

 

 

 

 

The new and improved open cases widget

 

new_open_cases_widget.png

 

Along with our upgrade of the Supportal to SBS 3.0, I took on the job of updating this widget to provide customers with better control over their open cases. There are two major upgrades that I gave this widget which have enhanced the way people use it:

 

1. Cases broken down by Severity

 

Instead of displaying all the open cases in a potentially enormous group, I've broken down the display into 3 distinctive parts. This is especially helpful for customers with more than 10+ open support cases at a time and allows customers to quickly see if they have any Level 1 issues that they need to attend to quickly.

 

2. New case option available: Priority

 

To the right of every case status is a set of up and down buttons which control the individual priority of every issue (within their respective severity).

 

 

 

 

 

Okay great, so how do I use it?

 

Step 1: Log in

 

Log into the Supportal and visit your Company's secure space "Overview" tab

 

overview.png

 

Step 2: Organize open cases

 

Browse through any open cases and use the "move up/move down" buttons to re-order them. All the moving on the screen will be done in real-time thanks to our good old friend Javascript. You may recognize these buttons from SBS, as they are used to control the location of profile fields on the admin console registration settings page.

 

priority_control.png

 

Step 3: Don't forget to Save!

 

As of right now, your cases will be in the order you want on the overview page, but there is one final step. You will need to click the Save Settings button at the bottom right hand corner of the widget. This will take the current ordering of your widget and persist the case priorities to the database.

 

save_settings.png

 

You will receive a friendly notification at the top of the widget that your Priority changes have been successfully saved, and you are done!

 

settings_saved.png

 

 

 

Well that's easy enough, how does it all work?

 

I'm glad you asked--it's really quite simple.

 

 

Displaying the widget

 

First off, the widget loads up all the non-closed cases within a secure space and puts them into three different Collections (one for each severity):

 

for (String caseID : caseIDs) {
    try {
        SupportCase supportCase = supportCaseManager.getSupportCase(Long.parseLong(caseID));
        String status = supportCase.getStatus();
        if (status != null && !caseStatusManager.isClosedStatus(status)) {
            String severity = supportCase.getSeverity();
            String priority = supportCase.getPriority();
            supportCase.setPriority(priority != null ? priority : "0");
 
            if(severity.equals("Level 1")) {
                openSev1Cases.add(supportCase);
                Collections.sort(openSev1Cases, new CaseComparator());
            }
            else if(severity.equals("Level 2")) {
                openSev2Cases.add(supportCase);
                Collections.sort(openSev2Cases, new CaseComparator());
            }
            else {
                openSev3Cases.add(supportCase);
                Collections.sort(openSev3Cases, new CaseComparator());
            }
        }
    }
    catch (NotFoundException e) {
        log.error("Could not retreive support case in OpenCasesWidget: " + e.getMessage());
    }
}

(Ideally this will get refactored soon to allow for more or less than 3 severities instead of being hard-coded. But it will work for now.)

 

 

The CaseComparator() orders all the currently open cases by their priority in the database. If nothing has yet been set, it will be put in the order that the cases were created.

 

 

The fancy effects

 

The cases are now sent to the template, where they are displayed in their respective severity grouping and automatically hooked into the Javascript functions that allow the up/down buttons to work. When you click on one of the buttons the following Javascript magic happens:

 

1. References to the required objects on the screen are loaded up using Javascript:

 

var moveUp = function(e, type) {
    Event.stop(e);
    var ansc = this.up(".case-field");
    if(ansc != undefined) {
        ansc.previous().insert({before: ansc});
        updateHiddenField(ansc, ansc.next());
    }
    updateOrderingAnchors(type);
}

 

2. A hidden priority field for each case is updated with the new ordering value:

 

var updateHiddenField = function(element, newElement) {
    var temp = element.select(".case-priority")[0].value;
    element.select(".case-priority")[0].value = newElement.select(".case-priority")[0].value;
    newElement.select(".case-priority")[0].value = temp;
}

 

3. The ordering of the case above (or below if the down arrow was pressed) will be swapped on screen and the list rebuilt:

 

var updateOrderingAnchors = function(type) {
    if(type == "1") {
        var elms = $("sev1-case-list-body").select("tr");
    }else if(type == "2") {
        var elms = $("sev2-case-list-body").select("tr");
    }else{
        var elms = $("sev3-case-list-body").select("tr");
    }
    elms.each(function(tr, i) {
        var anchors = tr.select(".field-moveup")[0];
        if (i <= 0) {
            anchors.update("<span class='move-up-disabled'>move up</span>");
        }
        else {
            anchors.update(new Element("a", {"class": "anchor-move-up", href: "#"}).update("move up"));
        }
        anchors = tr.select(".field-movedown")[0];
        if (i == elms.length - 1) {
            anchors.update("<span class='move-down-disabled'>move down</span>");
        }
        else {
            anchors.update(new Element("a", {"class": "anchor-move-down", href: "#"}).update("move down"));
        }
    });
    bindAnchors();
}

 

 

4. Now that the ordering is complete, you click the Save Settings button which makes a call to this Javascript to call a DWR method and display the nice notification at the top of the widget:

 

CasePriorityAction.setPriorities( values, {
    callback:function() {
        $('save-button').enable();
        $('jive-success-box').style.display = "block";
        Effect.Fade($('jive-success-box'),{delay: 3, duration: 5});
    }
});

 

 

 

Saving the data

 

The final step involves saving this to the database, which is done by the call to the setPriorities DWR method as noted above. This loops through all the cases on the screen and sets the priorities in the database accordingly:

 

public void setPriorities(List<String> values) {
    try {
        for(String value : values){
            String[] vars = value.split("-");
            SupportCase supportCase = supportCaseManager.getSupportCase(Long.parseLong(vars[1]));
            supportCase.setPriority(vars[2]);
            
            supportCaseManager.updateSupportCase(supportCase);
        }
    }
    catch (NotFoundException e) {
        log.error("Could not retreive case in CasePriorityAction: " + e.getMessage());
    }
}

 

 

 

I hope this information provides you with interesting insight into how our custom development allows us to work smarter and more efficiently with all our customers.  We want these new features to enrich your Jive experience!

 

As always, Jive welcomes any and all feedback about this feature and the Supportal in general.  Please comment on this post or start a discussion in our Supportal Feedback space.

1,889 Views 3 Comments Permalink Tags: jivespace, customization, support, development, widget, javascript, supportal, sbs

Supportal

This is the first in a series of upcoming blog posts where we will delve into the details behind our Supportal.  As most of our customers are already aware, the Supportal is Jive's Clearspace customization that transforms generic communities into personal communities where Jive collaborates directly with our customers via cases, documents, and projects.

 

This first post will provide the high-level overview, overriding design goals, business goals, and additional benefits to the Supportal.  Future posts will delve into the business decision details, and the architecture.

The Name

People often ask how the name Supportal came to be.  When it comes to overall creativity, I am horrible.  In this project's infancy, I used Customer Portal, Customer Support Portal, Support Portal, and many other terms as names.   Will French, Jive's Senior Support Engineer, and now the Supportal Development Lead, abbreviated Support Portal, to Supportal (likely making fun of me talking too fast), and the name stuck.  It also gets rid of that stigma around the word "portal" as well!

Reasons for the Supportal

The Supportal was created to resolve's Support's own business pains.  Prior to identifying the business pains however, we set 3 main overriding goals for the project:

 

  1. Simplicity: The goal of the supportal is to solve business pain.  Too many other support sites are tough to use and hard to navigate.  Creating a case needs to be as simple and easy as possible. We continue this philosophy on upcoming features, ensuring that additional features add benefit without causing pain.
  2. Accessibility: Customers weren't getting the information they needed, and people within Jive were not seeing the information they needed.  The solution needed to include as many people as possible, while still being private so that only Jive and the customer can see the information.
  3. Usability: Jive prides itself on this, and this is something that's always on our list.  Making the Supportal as usable as possible is also a guiding factor we focused on during the first iteration and continue to improve upon.

 

With the overriding goals set, we identified the following business goals:

  • Create a solution where customers can go to create all their cases, regardless of severity
  • Replace email with an online system as the mode of communication
  • Recreate survey information.  Associate the survey to the case.
  • Integrate Discussions (only community) with cases to provide customers with a single location to get their answer.
  • Provide customers the ability to create public cases, allowing others (outside Jive support) to read, contribute, and resolve, while ensuring that Jive Support will answer your issue.
  • Provide the same functionality (email) for customers who refuse to use the new system.
  • Remove manual customer and contract validation process

 

Solution

With the business goals identified, we realized that we had to integrate with our online community.  Clearspace provided communities (security for each customer), email notification, reply by email, discussions, and a means to replace email as the primary mode of communication.  80% of the work was done for us.  The missing parts were:

  • Auto-creation of customer communities via account, customer, and contract information in Salesforce
  • Validating customer ability to create cases upon user login
  • Adding meta data into customer community discussions, allowing them to become cases.
  • Customizing customer communities to show cases instead of discussions.
  • Synchronizing the cases (specifically the meta data) with Salesforce.
  • Paging for Severity 1 cases
  • Surveys
  • Creating cases via email

 

The following blog posts are going to delve into these sections providing more information behind each business goal, and how we customized Clearspace to solve the goal.

Additional Benefits

As with many solutions, we quickly realized that the Supportal can be used for more than just customer cases.  The first additional use case for the Supportal was identified when our professional services team started using Clearspace's project functionality within the Secure Communities.  This was exactly what Clearspace Projects were intended for, and the Supportal solved our PS department's communication requirements perfectily with no additional customizations.

 

We also have experienced a slight decrease in overall cases due to the increased visibility of the cases.  Managers will frequently apply a community watch so that they receive emails whenever anyone creates a case in their community.  We have had managers reply to a case telling us to disregard the case due to it being something they need to solve internally.  We have also had managers follow up with their team directly when issues are stagnating, allowing us to resolve issues quicker.

 

Finally, the public case feature is being used for about 7% of all of our cases.  Not a huge number, but definitely significant, and each additional case that is made public results in additional information in our community for others to see and use.  This stat is without us pushing the feature at all.

1,921 Views 5 Comments Permalink Tags: plugin, jive_software, community, customization, developers, support, supportal

Quick SSO on Clearspace 2.0

Posted by brockf Jul 1, 2008

Below is a small filter that I co-authored recently to integrate with Oracle Access Manager (formerly called Oblix). With the release of CS 2.0 we have totally revamped the authentication process and it is now built on spring-security (formerly acegi). Doing this makes it super easy for most of the typical SSO use-cases to be implemented in a reasonable amount of time.

 

Here was the use case:

1. User Makes initiial request and is not authenticated yet.

2. Webgate routes user to the corporate login page

3. User supplies auth credentials

4. Webgate authenticates the user

5. Webgate sets an Authentication Cookie that identifies this user to Webgate

6. Webgate adds custom HTTP Headers to a new request to the originally requested resource, in this case clearspace.

7. Clearspace ACEGI Filter chain executes for /*** path, this is where I inserted the OblixSSOFilter right before the form authentication.

8. The Filter executes, grabs the HTTP Header "jwt-dn" and extracts the users DN (the user name).

9. The Filter retrieves the User and creates an Authentication and allows the rest of the filters to execute.

 

The User is now authenticated. The Default authoprovider ultimatly loads the Users permission etc downstream using the default AuthProvider.

 

Here is the code for the filter. The filter is pretty straight forward. It looks at the incoming HttpServletRequest and attempts to retrieve a HTTP Header that was sent along from the webgate authentication form previously visited by the user, as stated above, in this particular scenario I was able to assume authentication would always be done prior to accessing clearspace.

 

 

 package com.jivesoftware.clearspace.sso.oblix;
 
 
import com.jivesoftware.community.aaa.AnonymousAuthentication;
import com.jivesoftware.community.aaa.JiveUserAuthentication;
import com.jivesoftware.base.*;
 
 
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.FilterChain;
import java.io.IOException;
 
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.Authentication;
import org.apache.commons.lang.StringUtils;
 
/**
 * Created by IntelliJ IDEA.
 * User: fred
 * Date: Jun 11, 2008
 * Time: 12:36:14 PM
 */
public class OblixSSOFilter implements Filter {
 
 
    private static String OAMHEADER = "jwt-unique";
    private static String HEADER_NAME = "jwt-dn";
    private UserManager userManager;
    //possible to use system properties to enable and change the header, for
    //now just keep it simple.
    private String oamHeaderName = HEADER_NAME;
    private boolean enabled = true;
 
    public OblixSSOFilter(){
        super();
    }
 
  
 
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        Authentication authentication;
 
        if(!enabled){
            filterChain.doFilter(servletRequest,servletResponse);
        }else{
            try {
                Log.debug("executing oblix filter");
                HttpServletRequest request = (HttpServletRequest)servletRequest;
                String oamHeader = request.getHeader(getOamHeaderName());
                if(oamHeader != null){
                    Log.debug("got OAM header: " + oamHeader);
                    String userDN = extractUserDN(oamHeader);
 
                    User authenticationTarget = null;
                    try{
                        authenticationTarget = userManager.getUser(StringUtils.chomp(userDN));
                    }catch(UserNotFoundException e){
                        Log.error("no user found with username: " + userDN);
                    }
                    //Found an a
                    authentication = new JiveUserAuthentication(authenticationTarget);
                    authentication.setAuthenticated(true);
                }else{
                    Log.debug("no OAM Header");
                    authentication = new AnonymousAuthentication();
                }
                    SecurityContextHolder.getContext().setAuthentication(authentication);
               }catch (Exception e) {
                    Log.error("Exception occured while trying to authenticate OAM response: " + e.getMessage());
               }
           
               
          filterChain.doFilter(servletRequest,servletResponse);
       }
    }
 
 
    private String extractUserDN(String header){
        String userName = null;
        String[] elements = StringUtils.split(header,',');
        for(String element: elements){
            Log.debug("processing header: " + element);
            if(element.startsWith(OAMHEADER)){
                String[] uniqueID = StringUtils.split(element,'=');
                userName = uniqueID[1];
            }
        }
        return(userName);
    }
 
    public void destroy(){
    }
 
    public void setUserManager(UserManager userManager) {
        this.userManager = userManager;
    }
 
    public AuthenticationProvider getAuthenticationProvider() {
        return authenticationProvider;
    }
 
    public void setAuthenticationProvider(AuthenticationProvider authenticationProvider) {
        this.authenticationProvider = authenticationProvider;
    }
 
    public String getOamHeaderName() {
        return oamHeaderName;
    }
 
    public void setOamHeaderName(String oamHeaderName) {
        this.oamHeaderName = oamHeaderName;
    }
 
    public boolean isEnabled() {
        return enabled;
    }
 
    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }
}

 

I simply created a jar containing this one class that I deployed to the WEB-INF\lib directory of a expanded clearspace war file. You can use any IDE or VI and Ant to create the jar, nothing special about it or clearspace specific.

 

After I had the jar. I needed to tell clearspace about the filter. Since 2.0 there is a back door that can be utilized to override the default implementation of clearspace managers,DAOs and other spring managed beans, this back door is your jiveHome\etc directoy. Within the jiveHome\etc directory you can copy and modify the various spring context files packaged in the clearspace.jar file found in \WEB\lib. This is done by extracting the appropriate spring context file from the clearspace.jar file found in WEB-INF\lib, make your edits to it and copy it into \jiveHome\etc. In my case the authentication filter stack is configured in spring-securityContext.xml so I extracted that and made the changes listed below:

 


<!-- NOTICE THE ADDITION OF oblixSS0Filter -->
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
        <property name="filterInvocationDefinitionSource">
            <value>
                CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
                PATTERN_TYPE_APACHE_ANT
                /upgrade/**=httpSessionContextIntegrationFilter, upgradeAuthenticationFilter, upgradeExceptionTranslationFilter,jiveAuthenticationTranslationFilter
                /post-upgrade/**=httpSessionContextIntegrationFilter, postUpgradeAuthenticationFilter, postUpgradeExceptionTranslationFilter,jiveAuthenticationTranslationFilter
                /admin/**=httpSessionContextIntegrationFilter, adminAuthenticationFilter, adminExceptionTranslationFilter,jiveAuthenticationTranslationFilter
                /rpc/xmlrpc=wsRequireSSLFilter, httpSessionContextIntegrationFilter, basicAuthenticationFilter, wsExceptionTranslator, jiveAuthenticationTranslationFilter, wsAccessTypeCheckFilter
                /rpc/rest/**=wsRequireSSLFilter, httpSessionContextIntegrationFilter, basicAuthenticationFilter, wsExceptionTranslator, jiveAuthenticationTranslationFilter, wsAccessTypeCheckFilter
                /rpc/soap/**=wsRequireSSLFilter, httpSessionContextIntegrationFilter, jiveAuthenticationTranslationFilter 
                /**=httpSessionContextIntegrationFilter, oblixSSoFilter formAuthenticationFilter, rememberMeProcessingFilter, feedBasicAuthenticationFilter, jiveAuthenticationTranslationFilter
            </value>
        </property>
    </bean>

<!-- DECLARE THE NEW FILTER -->
<bean id="oblixSSoFilter" class="com.jivesoftware.clearspace.sso.oblix.OblixSSOFilter">
        <property name="userManager" ref="userManager" />
    </bean>

 

 

As you can see the stack is configured to protect various resources within clearspace, you can add to this stack as required for your particular case, in my case it was simply a matter of declaring my filter, this allows spring to handle the creation of the object and changing the filter stack for the root path of the application to ensure the oblixSSOFilter fired off prior to formAuthentication. If the oblix filter is able to vouch for the user making the request (via the headers) the filter sets the Authentication on the SecurityContext and life moves forward with an authenticated user, if not, I allow it to fall to the next filter in the stack and the process repeats, with this new framework in place it makes it easy to support multiple authentication sources while still staying on the peripheral edges of the product which will help when it comes time to upgrade.

 

 

After you have made the changes, restart your clearspace instance and you should be up and running with your new filter.

 

Enjoy!.  

 

 

 

 

 

 

 

 

 

 

2,986 Views 11 Comments Permalink Tags: code, customization, sso, acegi, 2.0, spring-security

Learn the basics of how to develop a plugin for Clearspace 2.0 from Jive engineer, Jon Garrison. Jon talks about spring, struts, and more in this video.

 

 

You can also download the Quicktime version (Caution: file is ~140MB), or you can watch a larger version online, which will improve readability of embedded screenshots (recommended).

 

The entire presentation is also attached below as a PDF file.

 

1,239 Views 0 Comments Permalink Tags: podcast, video, clearspace, plugins, customization, customization

Theming in Clearspace 2.0

Posted by Dawn Foster May 12, 2008

As you know, we changed a few things in our underlying architecture for Clearspace 2.0, including some changes in the Freemarker templates as a result of moving from Webwork to Struts along with some other changes. In this video, Matt Walker, Professional Services Engineer at Jive Software, talks about the process of upgrading existing themes along with plenty of best practices to make your themes more easily upgradeable in the future.

 

Matt also did an earlier screencast as an Introduction to Skinning Clearspace, which you might also want to watch along with this video.

 

 

You can also download the Quicktime version (Caution: file is ~200MB), or you can watch a larger version online, which will improve readability of embedded screenshots (recommended).

 

The entire presentation is also attached below as a PDF file.

1,418 Views 2 Comments Permalink Tags: jive_software, jivespace, jivespace, podcast, video, clearspace, themes, freemarker, customization, struts, struts

Jive's Rick Palmer, Professional Services Engineer, takes about 5 minutes to explain how to insert dynamic content into your Clearspace FreeMarker templates. The slide below provides more details.

 

 

Or you can download the Quicktime Movie (Caution! 122MB)

 

1,184 Views 0 Comments Permalink Tags: jivespace, jivespace, podcast, video, themes, customization, template

Learn the basics of customizing your Clearspace theme in this introduction to skinning Clearspace with Matt Walker, professional services engineer (and juggler!) at Jive Software.

 

 

Or you can download the Quicktime version (Caution! ~100MB file)

 

You can also learn more about customizing Clearspace by visiting our documentation space!

1,863 Views 2 Comments Permalink Tags: jivespace, podcast, podcast, video, clearspace, themes, customization