Skip navigation

NOTE: This technique is valid only for Jive 6.0.1 and up.

 

Adding markup to the Jive application can be a challenge within the context of a plugin.  Well, I take that back.  It's easy to do, sure.  But doing it right?  A little harder than you might think.

 

Sure, you could just redefine a core Struts action in your plugin's struts.xml file and point it at your custom Struts action and/or custom Freemarker or Soy template.  But you know that doing so introduces risk.  Another plugin you install into your instance later on could override the same action, rendering one of them useless.  You may need to theme the Freemarker or Soy template that you modified, which would also wipe out the change made in your plugin.  You also are bound to that action and template's implementation for your version, which requires you to have to manually upgrade them each time you upgrade your Jive instance.

 

To get around that, you could always use Javascript, which you can include on every page in the system, that knows when to modify the DOM structure of the page, which is a pretty slick way to do it.  You can have your script detect which page you're currently on, and, when appropriate, invoke a Soy template, and append it to the DOM, thus modifying your view in a pretty upgrade-safe manner.  The problem with this approach becomes evident when you realize your custom page content requires server side data.  This means you need to make an AJAX call to a web service which you may or may not have to code up yourself, which totally works, but may not result in the best user experience, with the custom content being added to the DOM after a slight delay.

 

It would be great if we could somehow augment the data being returned by the Struts action in the first place, and have some sort of hook to add the markup that utilizes that data to the DOM structure.

 

Enter the PluginTemplateDefinition.

 

A PluginTemplateDefinition is a way to do just that.  Utilizing it requires the following:

  • Create PluginTemplateDefinition Java class implementation
  • Add your PluginTemplateDefinition class to Spring, and register it
  • Create a Soy Template

 

The Java Class

public class MyPluginTemplateDefinition implements PluginTemplateDefinition {

    @Override
    public boolean supports(Action action) {
        //only execute when looking at a place overview page
        return (action instanceof PlaceOverviewAction);
    }

    @Override
    public String getHeadTemplateName() {
        //no meta tags or css for this
        return null;
    }

    @Override
    public String getBodyTemplateName() {
        //template containing Javascript to modify the DOM
        return "jive.test.app.body";
    }

    @Override
    public Object getModel(ActionInvocation ai, Object actionModel) {
        //making available the data that I want
        Map<String, Object> model = new HashMap<String, Object>();

        Place place = ((PlaceViewBean) actionModel).getPlace();
        if(place.getObjectType() == JiveConstants.SOCIAL_GROUP) {
            List<String> owners = getSocialGroupOwners(place);
            model.add("owners", owners);
        }

        return model;
    }
}

 

The support() method simply checks whether this PluginTemplateDefinition should be executed for the current action.  In the case of this example, we only want it to execute when the PlaceOverviewAction is invoked.  If we wanted to execute on every page, we could just return true.

 

getHeadTemplateName() and getBodyTemplateName() will return fully-qualified soy template names.  The head template should only contain CSS includes and meta tag information.  In many cases, you won't need anything here, and can just return null.  The body template will contain the Javascript necessary to modify the DOM structure of the page being displayed.

 

In the getModel() method, you will create and return the data you want to be displayed on the page.  Here, you have access to the ActionInvocation itself, as well as the data returned by the action.  The actionModel parameter will be either a Soy model, for Soy-driven Actions, or the action itself, for legacy Struts actions.  You can access anything you want here, but should be wary of modifying any of the data in the model.

 

spring.xml

Registering your PluginTemplateDefinition is a matter of adding it to the list of plugin template definitions defined in Spring.  So, you would add the following to your plugin's spring.xml file:

<bean class="com.jivesoftware.community.util.spring.MergeableCollection" parent="pluginTemplateDefinitions">
    <property name="source">
        <util:list>
 <bean class="my.plugin.MyPluginTemplateDefinition" />
        </util:list>
    </property>
</bean>

 

Of course, if your PluginTemplateDefinition class has dependencies, you would define them here, as well.

 

Soy template

Your soy template will contain the Javascript needed to augment the DOM structure and display your data.

 

{namespace jive.test.app}

/**
* @param appParams
*
* @depends path=/resources/scripts/apps/my_amazing_js_app/main.js
*/
{template .body}
    {call jive.shared.soy.resourceInlineJs}
        {param id}plugins{/param}
        {param code}new jive.Amazing.App.Main({lb}buildJson({$appParams}{rb});{/param}
    {/call}
{/template}

 

This example assumes that you would be implementing some sort of complex, interactive visual layer on the screen.  If you're looking just for a simple inclusion of data on the screen, you could do something as simple as:

{namespace jive.socialgroupaccess}

/**
* @param owners
*/
{template .body}
    <script type="text/javascript">
        $j('#some-element').append('<p>{$owners}</p>');
    </script>
{/template}


 

Keeping in mind that you may also want to include another soy template here, rather than using HTML literals, just to keep things modularized.

 

Enjoy!

Idea

 

In this document I want to demonstrate a way to add customizations to Spring beans without overlaying/overriding the bean definition. This approach follows Kevin Conaway's ideas of modifying or adding functionality in an unobtrusive and repeatable (i.e. "multiple plugins or extensions can apply the same pattern to the same page without overriding or canceling one another", Freemarker Mixins) manner. These ideas and applicable solutions are described in these documents:

  • Freemarker Mixins: This article is focused on applying an unobtrusive and repeatable customization style on Struts action mappings and views (i.e. freemarker templates).
  • How To: Add Struts Interceptors at Runtime: This document describes how to add a custom Struts interceptor at runtime without extending the respective Action class in Jive or modifying (i.e. overlaying or overriding) the Struts action mapping.
  • Modifying Prototype Spring Beans: While the first two documents are about customizing the Struts Actions and UI templates, this article describes how to modify Spring beans with prototype scope (that means no singletons) without overriding the bean definition in a spring-*.xml file in a plugin.

After reading these three articles I wanted to find a way to customize some core Jive functionality without extending the Jive core classes or overriding the bean definitions. My first thought was to apply such customizations in an aspect-oriented (AOP) style, as Spring offers a lot of possibilities here. I spent a few minutes on trying to apply some advices via AspectJ-style by annotations and namespace/schema configuration, but neither worked: when using annotation configuration my IDE (Eclipse with AJDT) showed up compilation errors - I guess because the compile-time-weaver probably has to weave classes outside of the project; I don't know why the schema-based configuration did not work (perhaps I will investigate on this some time), so I switched to the "auto-proxying" approach, which did finally work, but I had to work around a few issues that came up with Jive (using 5.0.3).

 

Basics on Aspect-oriented Programming and Proxies

 

Most experienced Java (and especially Spring) developers will probably know the basics about aspect-oriented programming and proxying Java objects, but here is a brief introduction:

By most definitions out there, aspect-oriented programming is a programming paradigm that offers a modular approach to implement cross-cutting-concerns in object-oriented applications. Usually, a cross-cutting-concern is some technical or infrastructural functionality, that has to be applied to a lot of components in the application, like logging or transaction management. In terms of aspect-oriented programming, the cross-cutting-concern is the Aspect. The aspect is implemented in an Advice, which is often an Interceptor. An advice is applied to a Join Point, which is the point in the application where the aspect should be executed. Most AOP frameworks offer the concept of Pointcuts, which are expressions to define join points. Although I do not really want to implement a concern that is cross-cutting (I want to apply additional logic to specific beans), the general requirements and conditions for implementing plugins in Jive make AOP a nice way to implement additional functionality in a modular, unobtrusive (depends on implementation) and repeatable way.

 

In Spring, aspect-oriented programming is implemented through Proxies. A Proxy object is an object that encapsulates or wraps the target object (i.e. the actual bean object) and offers the same programming interface as the target class. By applying a proxy to a target object and using the proxy object as bean instance, all method calls to the target object (the join point of the bean) can be intercepted, which means that you can apply code or logic (the aspect) before and after the actual method calls happens. This additional code is implemented in a MethodInterceptor (the advice). Spring offers two ways for creating proxy objects:

  • JDK Dynamic Proxy API: included in Java, enables you to create proxies with defined interfaces. As these interfaces have to be Java Interfaces, you can only use this mechanism if you develop consequently against interfaces.
  • CGLib: third-party-library (included in Jive), that enables you to create proxies for Java classes. So you can use this mechanism if you develop against classes instead of interfaces (of course you can still develop against interfaces, too).

 

Implementing the MethodInterceptor

 

At first you have to implement the aspect as advice, which is a MethodInterceptor in this case. The MethodInterceptor is applied to all method calls (i.e. all join points of the bean), so in most use cases you will probably have to perform additional checks (like method names/signatures of the MethodInvocation) for executing your aspect's code. In my example use case, I want to perform additional checks after a user is authenticated by the "daoAuthenticationProvider" bean.

 

public class AuthenticationProviderInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        final Object result = invocation.proceed();
        if ("authenticate".equals(invocation.getMethod().getName())) {
            // perform additional checks
        }
        return result;
    }
}



 

Bean definition:

<bean id="mfAuthenticationProviderInterceptor" class="de.metafinanz.jive.security.AuthenticationProviderInterceptor" />



 

Proxying with BeanPostProcessors

 

A common way in Spring to define proxy beans is to use a ProxyFactoryBean that enables you to create proxies for a target object with defined interfaces to expose and interceptors to apply. If you want to use a proxy instance of this FactoryBean, you would have to use the ProxyFactoryBean's name to refer to it. But as we cannot (or do not want to) change all bean definitions that use or reference the target bean, a different approach is required. Luckily, Spring offers the concept of BeanPostProcessors. A BeanPostProcessor is a Spring construct to hook into the creation process of bean instances that allows you to modify and even replace instances before they are injected into other beans. If a BeanPostProcessor is defined as Spring bean and the application uses an ApplicationContext, the processors are registered automatically. For applying proxies to beans, Spring even offers an implementation of a BeanPostProcessor: BeanNameAutoProxyCreator. Configured with bean names for target objects (property "beanNames") and interceptors (property "interceptorNames"), this class automatically creates proxies according to the supplied configuration. One important setting is the "proxyTargetClass" boolean-property (default: false). If it's set to true, Spring will use the CGLib mechanism to create proxies.

 

Unfortunately, I got some errors in Jive when I used the BeanNameAutoProxyCreator (caused by a call to beanFactory.getAliases(beanName)). I did not look deeper into this issue - instead I created a similar class that only checks for the bean name and skips the check for aliases:

 

public class BeanNameOnlyAutoProxyCreator extends AbstractAutoProxyCreator {

    private static final Logger LOG = Logger.getLogger(BeanNameOnlyAutoProxyCreator.class);

    private List<String> beanNames;

    public void setBeanNames(String[] beanNames) {
        this.beanNames = new ArrayList<String>(beanNames.length);
        for (String mappedName : beanNames) {
            this.beanNames.add(StringUtils.trimWhitespace(mappedName));
        }
    }

    @Override
    protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
        for (String matchedName : beanNames) {
            if (isMatch(beanName, matchedName)) {
                LOG.info("Proxying bean " + beanName);
                return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
            }
        }
        return DO_NOT_PROXY;
    }

    protected boolean isMatch(String beanName, String mappedName) {
        return PatternMatchUtils.simpleMatch(mappedName, beanName);
    }
}



 

Bean definition:

<bean id="mfAuthProviderProxyCreator" class="de.metafinanz.jive.security.BeanNameOnlyAutoProxyCreator">
    <property name="beanNames">
        <list>
            <value>daoAuthenticationProvider</value>
        </list>
    </property>
    <property name="interceptorNames">
        <list>
            <value>mfAuthenticationProviderInterceptor</value>
        </list>
    </property>
</bean>



 

Registering BeanPostProcessors in Jive

 

As I mentioned before, BeanPostProcessors are automatically registered if an ApplicationContext is used. As Jive does use an ApplicationContext, the proxying should already work after defining the AutoProxyCreator. Unfortunately, there is a class com.jivesoftware.base.event.v2.AutoEventListenerRegistrar, which is a BeanFactoryPostProcessor. BeanFactoryPostProcessors do - as the name indicates - post-process bean factories and are registered and executed before BeanPostProcessors (see org.springframework.context.support.AbstractApplicationContext.refresh()). The AutoEventListenerRegistrar performs a lookup for beans of type com.jivesoftware.base.event.v2.EventSource to inject the EventDispatcher. By doing this, the beans will be instantiated and initialized (I don't know if this applies to all beans or only the resolved references, but all *Manager classes implement EventSource and these classes have a lot of dependencies). As the BeanPostProcessor is registered afterwards and the target objects are already created, the post processing is not executed for these instances. To work around this issue, it is possible to register the BeanPostProcessor manually. I did this by defining a bean that implements the interface BeanDefinitionRegistryPostProcessor. BeanDefinitionRegistryPostProcessors are also registered and executed automatically, but before the BeanFactoryPostProcessors (see org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory)). In this bean, we can register the BeanPostProcessor.

 

public class BeanPostProcessorsSetup implements BeanDefinitionRegistryPostProcessor {

    private static final Logger LOG = Logger.getLogger(BeanPostProcessor.class);

    private List<BeanPostProcessor> beanPostProcessors;

    @Required
    public void setBeanPostProcessors(List<BeanPostProcessor> beanPostProcessors) {
        this.beanPostProcessors = beanPostProcessors;
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory bf) throws BeansException {
        for (BeanPostProcessor bpp : this.beanPostProcessors) {
            LOG.info("Registering " + bpp.getClass().getName());
            bf.addBeanPostProcessor(bpp);
        }
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        // nothing to to
    }
}



 

Bean definition:

<bean id="mfBeanPostProcessorsSetup" class="de.metafinanz.jive.security.proxy.BeanPostProcessorsSetup">
    <property name="beanPostProcessors">
        <list>
            <ref bean="mfAuthProviderProxyCreator" />
        </list>
    </property>
</bean>



 

Summary (Pros & Cons)

 

The main reason for me to implement this approach was an additional plugin I had to develop: I needed to apply additional code after the daoAuthenticationProvider authenticates a user. I could have implemented this by extending the Jive class and overriding the bean definition, but I had already done this in another plugin (hence this was not repeatable). With this approach I am now able to add new behavior even to beans that are overridden in other plugins. I already have a use case, where a core bean is proxied by two separate plugins and it works perfectly.

 

But I think there are also two things you really have to consider before following this approach:

  • Implementation: you need to know the implementation of the target method and have answers to the following questions: What happens if I modify the method parameters? Which exceptions does the target method throw and how are they handled by callers? How is the result object used by callers and what happens if I modify the result object? If you use this approach, the aspect's code should be as unobtrusive as possible. If you modify method parameters and execution results, this is likely to affect the stability of the system and the repeatability of the approach. You also have to take other applied aspects into account, like transaction management for instance (transaction boundaries!).
  • Product upgrades and API conformity: the code of an implemented aspect/advice is not "type-safe". In the MethodInterceptor you probably evaluate the method name and signature and cast Objects to interfaces or classes. If the method name or signature changes with new versions, your advice might not work anymore or cause errors at runtime.

 

Comments and opinions on this approach are very welcome. Can you think of any drawbacks I might have missed? Has anybody done something similar yet and what are your experiences?

SQL Query Examples

Posted by surfwthsharks Feb 15, 2013

Please post any SQL Query examples here so that we can help future Jive users get the most out of their Jive system.  Remember, computers are for input/output and the more information that is available to help with the output side of things the more Jive will be utilized.

 

Here is on example of a query that gets users and total Points:

select p.user_id, u.firstname, u.lastname, u.email, sum(p.points) as points from jivedw_statuslevelpnt p

inner join jivedw_user u on p.user_id = u.user_id

where u.userenabled = 1

group by p.user_id, u.firstname,u.lastname,u.email

order by points desc

 

Can anyone share a SQL query that shows the number of points a user has in any specific space?

amit.mahajan

How jive works

Posted by amit.mahajan Feb 5, 2013

Jive is set of latest technologies bought together and applied to emerging domain of social software.

 

Here are few technical details about how jive 5 actually works and what technologies are inside

 

Technical stack

 

Spring: Spring framework is the mother board for jive and it connects all the components together without having them depending on each other.

It contains various components like Core, AOP, JDBC etc which are very easy to use and light weight.

 

Struts: This is web/view layer of Jive which includes MVC design pattern and has SOY/Freemarker based views. This is one of the most popular MVC framework and is easy to use well documented framework. It also provides lots of build in features like action support classes, UI components, Tokenizer, Validation and flow control.

 

Sitemesh:  This component decorates the UI with header footer and common elements.

 

Apache CXF: This is used for exposing functionality as webservices. Jive 5 uses JAXRS based RESTFul webservices.

 

How jive starts up

 

Jive as any other web applicaton has web.xml descriptor which controls its lifecycle.

 

Web.xml  -> DelegateFilterProxy (many pre and post processing elements)

                    |

                    -> JiveApplicationContextLoaderListener (Bootstraps Spring along with ContextConfigLocation element

                         |

                         -> JiveContextLoader (loads all the spring configuration files)

                         |

                         -> spring-setupWebContext (loads all the struts MVC) -> strutsFilter

 

 

Along with this Jive has customized Freemarker manager which sets global static properties to be available across the views.