Skip navigation
1 2 Previous Next

Jive Plugin Developer

20 posts

A while back, it was reported that Javascript files that were overlaid in the web/src/main/overlay directory were not being properly minified as part of the build process.  I'm happy to say that this issue has been addressed in the latest version of the jive-parent-pom for Jive versions 6.0.3.4 and up.  Getting the fixes into your project is easy.

 

The next time you build your project, you should see a message similar to the following:

 

[INFO] ************************************************************************************************************************************************

[INFO] Checking for newer versions of jive-parent-pom...

[INFO] You are currently using version 6.0.3.4-3 of jive-parent-pom.

[INFO] The latest version of jive-parent-pom is 6.0.3.4-4

[WARNING] You are not using the latest version of jive-parent-pom.  It is strongly recommended you update your project POMs to reflect this, as follows:

[WARNING] <parent>

[WARNING]     <groupId>com.jivesoftware.maven</groupId>

[WARNING]     <artifactId>jive-parent-pom</artifactId>

[WARNING]     <version>6.0.3.4-4</version>

[WARNING] </parent>

[INFO] ************************************************************************************************************************************************

 

Just follow the instructions, and modify your root POM's <parent> element to point to the appropriate version. 

 

Before rebuilding your project, however, you'll need to make one more change.  In your /web/pom.xml file, remove the following dependencies, as they are no longer needed:

        <dependency>

            <groupId>com.jivesoftware</groupId>

            <artifactId>yuicompressor</artifactId>

        </dependency>

 

 

        <dependency>

            <groupId>com.jivesoftware</groupId>

            <artifactId>yuicompressor-anttask</artifactId>

        </dependency>

 

 

Once you have made these changes, you can rebuild your project, and note that your overlaid Javascript is once again being properly minified.

 

Please reply if you have any questions about this change.

 

Thanks!

Hey everyone.

 

I wanted to let everyone know that we have added full support for Jive 7.0.2.0 to the Jive Maven Unified Archetype.  We created the new 7.0.2.0-compatible version of the jive-parent-pom in conjunction with the 7.0.2.0 GA release on Monday, so you technically have been able to create 7.0.2.0 projects since that time, but the archetype was missing some 7.0.2.0-specific search settings, which could have led so your local search server not starting up correctly. (See the end of this post for details)

 

To recap, in order to create your new Jive 7.0.2.0 project, just enter the following on your command line:

 

$ mvn -U jive:create-project

 

Be sure to specify "7.0.2.0" when prompted for a Jive version.

 

If you already have a Jive project, and want to upgrade it, you can easily start the process by entering the following command at the root of your project, entering "7.0.2.0" when prompted:

 

$ mvn -U jive:upgrade

 

If all this jive:whatever-whatsthisnow craziness is new to you, be sure to check out Announcing Jive Maven Archetype Changes and Moar Archetype Changes! Now Simpler Than Evar!

 

Also, if you're upgrading, and want to incorporate any changes in the archetype into your project, check out and follow Maven Unified Archetype Release Notes.

 

 

Ok, so if you got super excited, and created a new 7.0.2.0 project before this blog post was published, you'll need to make a few changes.

 

If you run the start-search script in the run-services directory, you'll see the following error message:

 

/---------------------------------------------------------------------------------

The follwoing properties are missing and need in-order to start the service.

CONTENT_SEARCH_FILTER_CACHE_ENABLED=true

CONFIG_DIRECTORY=./etc

CONTENT_SEARCH_FILTER_CACHE_SIZE=1000

CONTENT_SEARCH_FILTER_CACHE_TIME_MILLIS=600000

 

 

Add the properties to /path/to/my/project/run-services/main-args.properties and restart the system.

\---------------------------------------------------------------------------------

 

But HOLD ON, because if you add those properties exactly as displayed, your search service won't start up properly, and will just hang.  You'll need to modify the CONFIG_DIRECTORY property to be ./var/data/directory.  Add the following lines to the end of your main-args.properties file:

 

CONTENT_SEARCH_FILTER_CACHE_ENABLED=true
CONFIG_DIRECTORY=./var/data/directory
CONTENT_SEARCH_FILTER_CACHE_SIZE=1000
CONTENT_SEARCH_FILTER_CACHE_TIME_MILLIS=600000

 

 

As always, we welcome your feedback.  Thanks!

Upgrades Made Easy(er)

Posted by kyanring May 10, 2014

Before you read this post, check out:

 

 

Our recent changes to the Maven archetype, including the inception of the jive-parent-pom, are aimed at making it easier to do those mundane, yet error-prone, tasks around project creation, as well as alerting you to new changes to dependencies and build configuration.  As I mentioned in my last post, your build will tell you if there is a newer release of the jive-parent-pom for your version of Jive.  While this is all well and good, it doesn't help you upgrade your custom project or plugin.  For instance, if you want to upgrade from 7.0.0.2 to 7.0.1.0, you would have to change the version of the jive-parent-pom dependency in the <parent> element of your project's pom.xml file, somewhat blindly, from 7.0.0.2-1 to 7.0.1.0-0, build the project, and see if you needed to change the version again to something like 7.0.1.0-1.  While this is still easier than search for the proper jive, EAE, search, Spring and AspectJ versions for the version of Jive you're upgrading to, it's still not ideal.  That is about to change.

 

The jive:upgrade goal is here!

 

Note that the following is only valid with projects and plugins that were created with the new jive:create-project and jive:create-plugin Maven goals.  You'll need to upgrade any projects you have created using the old maven-jive-archetype or maven-jive-plugin-archetype before you can use this.

 

This goal can only be executed from your root project, or your independently-created plugin (not within a Jive project).  Just run the following command:

mvn -U jive:upgrade

 

You will be prompted to type the Jive version to which you want to upgrade.

 

You are current using Jive version 7.0.0.2. Which version of Jive do you want to upgrade to?: 7.0.1.0

 

All you have to do is enter the full Jive version.  The goal will then automatically detect the latest jive-parent-pom release for that version of Jive, and change the version within your project's pom.xml file.

 

[INFO] Applying com.jivesoftware.maven:jive-parent-pom version 7.0.1.0-3 to /Users/ryan.king/code/test/upgrade-me-again/pom.xml

[INFO] Applying com.jivesoftware.maven:jive-parent-pom version 7.0.1.0-3 to /Users/ryan.king/code/test/upgrade-me-again/run-services/pom.xml

[INFO] Be aware that you may need to change the contents of the following files:

[INFO] run-services/serviceconfig/core.json

[INFO] run-services/main-args.properties

 

While this sounds perfect, there is a caveat.  Sometimes, upgrading from one version of Jive to another requires that you change some files.  Once you complete this process, you may need to make those changes.

 

Stay tuned, as more changes are coming!

 

As always, post your comments and feedback here.

A couple of weeks ago, I wrote a post Announcing Jive Maven Archetype Changes.  This was just the first step in a series of changes to make both the use and the management of Jive Maven archetype-generated projects easier.  The first step, described in the aforementioned post, discussed the new unified archetypes, which, going forward, will support Jive 6, 7, and beyond. Next, we abstracted the archetypes altogether with the creation of the Jive Project Plugin for Maven, described in How To: Create a Custom Jive Project, making the generation of a project as easy as typing a simple, easily-rememberable command, which will always pull from the latest version of the unified archetypes, so you get all the latest improvements for your new project.

 

While these first steps make project and plugin creation a cinch, they don't help much with maintaining your project.  You still need to know which version of Jive to point to, and which versions of the EAE and Search server libraries to use for that version. We tried to make that a bit easier with Jive EAE/Search Dependency Map, but it's still ultimately a manual process to upgrade them, and still quite error prone.  Not only that, but the project POM files are kinda huge.  We use lots of plugins and dependencies in our projects, and they are repeated, over and over again, every time you create a project.  As we changed things, such as AspectJ or Spring library dependencies, or Maven plugin configurations, there was really no way to get them to you, the developer.  You were pretty much stuck with generating a new project from the latest archetype version, and performing a diff against your existing project.

 

Well, those days are gone.

 

I'm thrilled to tell you about new changes to the Jive Maven Unified Archetype (and the Jive Maven Unified Plugin Archetype) that simplify version management, decrease the size of your project POMs, and help keep your builds up-to-date with the latest changes.  Best of all, this is already available to you.

 

First things first:  You'll need to upgrade your Maven installation.  Unfortunately, some of the awesome features we wanted to use were only available in Maven 3.2.1.  Go get it here.

 

If you follow the instructions in How To: Create a Custom Jive Project, and execute the command to create a new project..

 

mvn -U jive:create-project

 

...and follow all the prompts, on the surface, your new project will look the same.  If you look a bit closer, however, you'll see the difference.  Check out the project's root pom.xml file.

 

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <name>demo-project</name>
    <groupId>com.jivesoftware.demo</groupId>
    <artifactId>demo-project</artifactId>
    <version>1.0-d1-SNAPSHOT</version>
    <description>Jive customization project. This is the parent pom</description>
    <packaging>pom</packaging>

    <parent>
        <groupId>com.jivesoftware.maven</groupId>
        <artifactId>jive-parent-pom</artifactId>
        <version>7.0.1.0-2</version>
    </parent>

    ...
</project>


 

Notice the new <parent> element.  This references the new jive-parent-pom, which enables us to do all those things we mentioned above.  If you click the link, and take a look at the POM itself (after authenticating to our Archiva server, of course), you'll see that we pushed all the dependency and plugin management up into this new parent POM.

 

Now, all those nasty versioning details are completely abstracted.  The versions you need for the Jive, EAE, Search service, AspectJ, Spring libraries, are all defined for you, and you won't need to change them.  But if, for some reason they do need to change, all you'll have to do is change which version of the parent POM your project is pointing to (from 7.0.1.0-2, for example, to 7.0.1.0-3), and you'll get all those changes.  This does not only apply to versions, but also to Maven plugins.  Whereas before all plugins were explicitly defined in the root, web, and plugin POMs, now they are defined in the parent POM, and merely referenced in the individual POM files.  Each plugin's configuration is hidden where possible, and each POM that needs it simply references it.  As you can imagine, this makes the POMs themselves much smaller.

 

Fun Fact:  We reduced the size of the root POM file from 318 lines, to 77 lines.  The web POM is still kinda hefty, due to the cargo configurations, but it, too, shrunk in size a great deal, going from 520 lines, down to 331.

 

At this point you might be asking yourself how a developer might know that new changes are available in a new version of the parent POM, and you'd be right to do so.  After all, the whole point of all these exercises was to simplify things and get our developers out of the business of keeping track of which versions of what to use, so what gives?  My answer to you would be this:

 

Your build will tell you.

 

Tucked away into the <plugins> section of the jive-parent-pom is a little plugin called jive-parent-pom-version-check-plugin, which contains a goal which is run every time you perform a build.  During the validate step of the project lifecycle, it will check Maven to see if another, newer, version of the jive-parent-pom is available, and will display a message if that is the case.  For instance, if my project was using version 7.0.1.0-1 of the parent POM, I would see the following message when building my project:

 

[INFO] Checking for newer versions of jive-parent-pom...

[INFO] You are currently using version 7.0.1.0-1 of jive-parent-pom.

[INFO] The latest version of jive-parent-pom is 7.0.1.0-2

[ERROR] ************************************************************************************************************************************************

[ERROR] You are not using the latest version of jive-parent-pom.  It is strongly recommended you update your project POMs to reflect this, as follows:

[ERROR] <parent>

[ERROR]    <groupId>com.jivesoftware.maven</groupId>

[ERROR]    <artifactId>jive-parent-pom</artifactId>

[ERROR]    <version>7.0.1.0-2</version>

[ERROR] </parent>

[ERROR] You can bypass this error by setting the ignoreNewVersion property to "true"

[ERROR] ************************************************************************************************************************************************

 

At this point, you would have the option of changing the version to the recommended version, and you're golden.  And when it comes time to upgrade, it's just a matter of changing your jive-parent-pom version to the appropriate version, and then dealing with compile errors, etc.

 

Transparency Time:  As I type this, I understand that it's not entirely obvious, when it is time to upgrade, which version to change to.  For now, this will be a trial and error process.  Simply change the version to the next Jive version, and add a -0.  Your build will tell you if:
  • a parent POM for that version of Jive exists
  • whether a new version for the parent POM exists for that version of Jive (like -1 or -2 ) exists

 

Look for another blog post soon that details some new cool ways to know what versions of the jive-parent-pom are available, right from your command line.

 

If you have read this, and are wondering how you can get these changes into your existing project without having to scrap everything and start over, well there's good new and bad news.

 

The good news is, yes, you can definitely do this!  The bad news is, you have to do it the old way, by creating a new project, and then performing a diff on your root, web, run-services, and plugin POMs.  However, you only have to do it this one last time!

 

For plugins that exist within the context of a project, they should still use the root project as their parent, but will still get all the parent POM goodness through inheritance.  Independent plugins, on the other hand, which do not live within a root project, should reference the jive-parent-pom directly, as its parent.

 

Hold On, Right There:  The new jive-parent-pom is only available for Jive 6.0.3.4 and up.  If you're still using Jive 5, or an earlier version of Jive 6, you'll need to wait to get this until you upgrade.  So upgrade, already!

 

As always, we welcome your feedback.

 

Thanks!

Hello all,

 

We have been working hard over the past few weeks on the latest set of changes Jive's Maven archetype, which I am happy to highlight here.

 

Unified Archetype

 

Each time a new major version of Jive has been released (5.0, 6.0, 7.0) we have created a new version of our Jive Maven archetypes.  This has allowed for the easy inclusion of modules or elements specific to that new version.  Additionally, the archetypes have been never really been released, and have been left as SNAPSHOTs.  This has enabled developers, each time they create a new project or plugin, to get the most recent version of of the archetype, along with any fixes or improvements therein.  Honestly, this has always felt a little weird.  While it makes sense from a practical standpoint, we're not really following any best practices by doing so.  We didn't want anyone to miss out on the latest just because they got the version number of the archetype wrong, specifying version 7.0.0.1, for example, when there's a really great fix in 7.0.0.2.

 

That's all changing today, with our new jive-maven-unified-archetype (and jive-maven-unified-plugin-archetype).  The unified archetype will support both 6.x and 7.x Jive projects.  It will also be versioned with each change.  But that's ok because we are also releasing a new Jive Maven Plugin, called jive-project-plugin.  With a few tweaks to your settings.xml file, you'll now be able to create a new custom project without ever dealing with the archetype directly, or knowing the name of its latest version.

 

You'll now be able to create a project simply by running the following on the command line:

mvn -U jive:create-project

 

or a new plugin with:

mvn -U jive:create-plugin

 

You will then be asked questions regarding the kind of project you want to create, including:

  • Jive version (and, yes, EAE and Search versions will be changed accordingly)
  • Project group ID
  • Project artifact ID
  • Instance type (internal or external)

 

It's all detailed in How To: Create a Custom Jive Project.  We definitely welcome your feedback should you experience any problems using it, or have any suggestions for improvement.

 

 

Themery

 

Historically, custom themes have lived in the web module, in the /src/main/themes directory, of our maven-jive-archetype.  This has worked pretty well to this point, but changes we have made to our build environment at Jive dictated that we make a change.  Under the new jive-maven-unified-archetype, themes have been moved out into its own module, as a peer to the web module. 

 

Screen Shot 2014-03-10 at 6.57.03 AM.png

 

We have worked on a number of customer projects lately that have consisted of only Jive plugins and custom themes, with no custom WAR (which is a good thing!).  However, with the themes tied to the web module, that meant that we always had a WAR artifact to deploy to Maven, empty or not.  That's over 100MB per deployment.  Over time, and with all our customers, that amounts to a ton of wasted space.  Now, when you build your project, the themes module will produce its own binary artifact, themes-<version>.zip

 

EAE and Search

 

The run-services module has had an awkward existence since its creation in the 6.0.x version of the maven-jive-archetype.  If you leave it as a module, referenced in the root POM, it gets built and potentially deployed to Maven upon release.  To avoid this, we have made a couple changes to prevent this.

  1. run-services is no longer a module in the root POM
  2. The <parent> reference to the root project has also been removed from the run-services POM.
  3. <eae.version> and <search.version> properties have been moved from the root project to run-services.

 

These changes give the run-services project a sort of transient existence, in that it's still useful when running your Jive instance locally, but will never be built or deployed if you leave things alone.

Between unit and integration testing

 

Everyone knows that it is mandatory to implement automated software tests that run on every build, commit or on a continuous integration system to ensure the quality of your developed software and to find bugs before a user has to experience it. The most common way to do this is to implement unit tests to verify the functionality of very small-grained code units (i.e. classes). Depending on your development process, you maybe even implement these test cases based on your requirements before you implement the software itself. But in some environments and for some software components it is very time-consuming to implement a unit test for every component, especially if the unit has a lot of dependencies that have to be mocked by using a mocking framework like Mockito or EasyMock. To write a unit tests for a plugin's Manager class that uses other Manager classes from the Jive core, you have to mock all of these dependencies. Some components like DataAccessObjects (DAOs) are even harder to test because you have to find a way to mock a RDMS. To test your software "in action" (i.e. against a running RDMS), you can of course implement automated integration tests with frameworks like Selenium that run on the frontend of your application. However one drawback of this approach is that you have to rewrite tests very often with every change of the UI. If you have only little control over the system's UI (as you have when developing plugins for Jive), you might have to rewrrite the whole UI and all the tests with it with every new major version.

These drawbacks made us look for another way to test our plugins that is not too time-consuming, not that affected by Jive UI changes but can test the plugin functionality regarding the interaction with the Jive core components. This blog post describes the found solution that uses a testing framework that is implemented by and is delivered with Jive.

 

Functional testing with JiveCommunityTest

 

The core base class for implementing automated functional tests for Jive plugins is the class com.jivesoftware.util.JiveCommunityTest located in com.jivesoftware:core-test-base. The JavaDoc for this class reads as follows:

This class is an extension of jUnit's TestCase. It is designed to be used as a functional test harness. A functional test is a test which needs various system resources set up -- a database connection, config files, etc. By simply extending this class you can call any Jive APIs and be assured there is a clean database underneath the hood.

 

If you use this class as base class for your custom JUnit test, it will start up (@BeforeClass) and tear down (@AfterClass) an environment that is very close to the real jive-application:

  • Create the spring application context
  • Create an in-memory database (HSQL) or setup up the schema on an existing database like Oracle, PostgreSQL,... (see com.jivesoftware.util.bellerophon.TestDatabaseProvider for details)
  • Setup jive home directory

 

Extending the Spring application context

 

So imagine having a class CustomManager in your plugin that has dependencies to Jive's UserManager, GroupManager, TagManager, ... and now you want to create an automated test class for it.

To implement your CustomManagerTest, you just have to create a test class that is derived from JiveCommunityTest:

 

@Configurable(autowire = Autowire.BY_NAME)
@SpringContext("classpath:spring-customTestContext.xml")
public class CustomManagerTest extends com.jivesoftware.util.JiveCommunityTest {

    private CustomManager customManager;

    @Required
    public void setCustomManager(CustomManager customManager) {
        this.customManager = customManager;
    }

    @Test
    public void perform() throws Exception {
        Assert.assertTrue(customManager.works());
    }
}





 

By default, the base class starts up the Spring application context that is defined in classpath:spring-testApplicationContext.xml. As you need an extended context here (containing the configuration for the plugin's beans) you have to create a new file spring-customTestContext.xml that includes the plugin's spring.xml and Jive's spring-testApplicationContext.xml:

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" [...] >
    <import resource="classpath:spring-testApplicationContext.xml" />
    <import resource="classpath:spring.xml" />
</beans>




 

You also have to ensure that the classpath is correctly set up when running the tests.

 

Extending the database schema

 

Jive offers the possibility to extend the database schema by plugins. To achieve this, you just have to describe your tables in XML in a file called schema.xml. When running a test based on JiveCommunityTest this additional schema is not automatically created by the test class. To prepare the test database for your plugin test, you can use the class com.jivesoftware.util.bellerophon.TestDatabaseProvider to obtain the database configuration and create the required schema.

 

@BeforeClass
public static void setupSchema() throws Exception {
    final DatabaseProperties props = TestDatabaseProvider.getDatabaseProperties(DatabaseTypes.HSQL);
    TestDatabaseProvider.createSchema(props, CustomManagerTest.class.getClassLoader().getResourceAsStream("schema.xml"));
}




 

By using the @BeforeClass annotation, the custom schema is created after the base class' setup is performed but before any of the tests contained in this class is executed.

It is also possible to call the createSchema() method again to prepare the database with additional test data that is defined in another XML-File.

 

Creating places, content, users with FunctionalTestUtil

 

Many test cases depend on existing users, groups, permissions, places or content in a jive application, that are not present when a clean database is set up for every test run. You can of course - as described in the section above - define another schema.xml file that creates the required jive objects, but that requires a deep knowledge of what is implemented in the jive core.

The better solution is to use the class com.jivesoftware.util.FunctionalTestUtil that provides lots of helper methods to create and link these core jive objects, for instance:

 

User user = FunctionalTestUtil.createTestUser("john.doe", "***", "john@googlemail.com");
SocialGroup socialGroup = FunctionalTestUtil.createTestSocialGroup("John's private group", user, DefaultSocialGroupType.PRIVATE);



 

Running multiple test classes in the same context

 

The start up of the environment for one test class obviously takes some seconds to minutes. To keep tests maintainable a developer will prefer to implement test cases grouped by components in multiple test classes. The more test classes you derive from JiveCommunityTest, the longer the test execution for your plugin will take. But fortunately, JiveCommunityTests offer the possibility to create a shared environment to be used by multiple test classes. To configure this mode, you just have to run your tests with an additional parameter: -Djive.test.oneContext=true

 

Conclusion

 

Implementing automated functional test cases with the described framework by Jive is a great possibility to test your developed components against the jive core components. As you nearly don't have to spend any time to mock your component's dependencies, you can focus on the actual business logic of the test case. Another advantage is the possibility to run your tests against a real RDBMS and to use a defined and clean schema and dataset for every test run.

Many times it is difficult to find which table or tables some information is saved.

It involves searching documentation, debugging and looking at code.

 

This sql query is useful in this (at present the query is for postgres database)

 

SELECT ('select ' || column_name ||  ' from ' || table_name || ' where '||  column_name ||  ' like ''%?%''; ') 

FROM information_schema.columns c

WHERE c.table_name in (

SELECT table_name

FROM information_schema.tables where table_schema = 'public'

) and c.data_type='text'

 

This post of mine explains a simple solution DATABASE Blog

 

This is useful for developers who are new to jive and want to learn how the data gets stored and to debug in better informed way.

I just work on a jive plugin with should modify blogPost. And for me it looks like there is something wrong or weird in the internal Api.

 

In the interface com.jivesoftware.community.BlogPost if found this:

 

/** 
 * Saves the state of this BlogPost to the database 
 * 
 * @param fireModifiedEvent true if a modified event should get fired after the blog is saved. 
 * @throws UnauthorizedException If the user is not allowed to modify this blogpost 
 * @throws IllegalArgumentException if the subject has already been used on this blog on the given publish date 
 */  
void save(boolean fireModifiedEvent) throws UnauthorizedException;  

 

 

In the implementation of com.jivesoftware.community.impl.DbBlogPost the method signature looks like this:

 

@Transactional(readOnly = false, propagation = Propagation.REQUIRED)  
public void save(boolean runInterceptors) {  

 That doesn't match. And when i look further in the method I found this:

// In the case of a moderated post we don't want to send a modified event  
// before sending out a created event.  
// That only happens when the status is changed from PUBLISHED to AWAITING_MODERATION. Fixed    
if (!(existingPost.getStatus() == Status.PUBLISHED && this.getStatus() == Status.AWAITING_MODERATION )) {  

boolean shouldFeed = this.getStatus().isVisible();  

    Map<String, Object> paramMap = new HashMap<String, Object>();  
    paramMap.put(BlogPostEvent.KEY_EXISTING_POST_STATUS, existingPost.getStatus()); 

    BlogPostEvent event; 

if (existingPost.getStatus() != Status.PUBLISHED && shouldFeed) {  
        event = new BlogPostEvent(BlogPostEvent.Type.CREATED, this, paramMap);  
    } else {  
        event = new BlogPostEvent(BlogPostEvent.Type.MODIFIED, this, paramMap);  
    } 

    event.setShouldFeedActivity(shouldFeed); 

    JiveApplication.getEffectiveContext().getEventDispatcher().fire(event); 
} 

So it looks like a blogPost event is fired when

 

!(existingPost.getStatus() == Status.PUBLISHED && this.getStatus() == Status.AWAITING_MODERATION )

 

So for me. It looks like the save(boolean fireModifiedEvent) does fire modified events when the parameter is set to false. Does anybody know how i can save a BlogPost without firing a modifed event. Only with the BlogPostBean?

 

Thanks

Jens

The jive 5 has many imporvements in terms of webservices. There are primarily REST and SOAP based services and some places both*.

 

Most of the existing webservices wount work directly on new version due to changes like form based RESTFul services.

Meaning that the webservices will need to be called by submiting a form to a URL with inputs passed as form input elements.

 

Underlying jive webservices is apache cxf framework. This is plugged in using spring component.

 

Follownig configurations are needed to create a webservice in this approach

 

REST

 

Spring


jaxrs element with id, address and implementing bean reference. This entry along with bean and annotations on bean interface is used to declare a web-service.

 

Example Spring.xml

<jaxrs:server id="custom-service-name" address="custom-servie-address">

        <jaxrs:serviceBeans>

            <ref bean="custom-service-manager-bean" />

        </jaxrs:serviceBeans>

          ...

    </jaxrs:server>

  

Implementing Interface

Bean interface has annotations @GET/@POST/@DELETE and @Path element which has location of the individual method. @PathParam is used to extract elements from path to method parameters. @FormParam can be used to extract data from post.

 

 

Differenct between @GET and @Get

Both are used for RESTFul services but @Get from codehus is used when we use both SOAP and REST over same service implementing class.

 

When to use REST and when to use SOAP

SOAP is a approach of integrating large applicaitons where interface complexity is high. For Jive REST services are sufficient to expose it's functionality in simple and efficient way.

But there are some drawbacks that i fealt (There may be workarounds to these limitations and it will be great if you can provide your valuable comments)

1.  The RESTFul services dont have WSDL files - So in case one know the service address it is hard to find list of available methods, the interface for calling them etc...

2. There is less control while calling webservices while using JSON approach of data transfer. In case we use XML approach, where is the definition of the XML elements?

So in case we would like to modify the payload of xml/json message on the fly it will be difficult since the definition is not well defined like that in SOAP (SOAP WSDL has Schema element)

 

SOAP should be used when there is a need to consume services from complex applications. The use of SOAP should be minimum since it involves lot of parsing and preprocessing, on the other hand it also has good integration with SOA architecture and easy to integrate with complex systems.

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.

Not much information to share here, but it will no doubt be a sticking point for many developers.

 

In previous versions of Jive, the value "jive.version" was:

<jive.version>5.0.4.0</jive.version>

or something similar.

 

For Jive 6, currently unknown by me since I am not in engineering, the value for Jive 6 needs to be:

<jive.version>6.0.0.0_RC8</jive.version>

not

<jive.version>6.0.0.0</jive.version>

More information to come on this, but wanted to get this out ASAP so my fellow developers could get this party started!

 

Hope this helps. =)

This year, Jive will be hosting the OpenSocial State of the Union working session at our Portland office. OpenSocial is the key technology behind our apps framework and this will be where we'll be defining some of the "next big things" that will work themselves into the specification. We'll have broad industry participation from the likes of IBM, SugarCRM, and many others.

 

We'll also be celebrating with the Apache Community another great year of moving the social web forward through open source at the Apache Shindig / Rave "Beer Forge". Jive a contributor to a number of open source projects, including Apache Shindig, the core underlying code of the apps framework. This will be a great way to meet and network with the developers that are building some of the great code that powers Jive and a number of the other social platforms. If you happen to be in Portland on July 17th, then come and join Jive and the OpenSocial and Apache communities for a great evening!

 

I hope to see you there!