com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links' is unknown.

LoginListener

The LoginListener interface is a well-defined extension point provided by WSO2 Carbon. This provides an API that allows you to register a logic that should be executed when a user logs in. The onLogin() method will be invoked during a successful login and all your preferred actions should be defined within the implementation.

 WSO2 provides an API called LoginSubscriptionManagerService, which allows Login Listeners to subscribe to it. During a successful login session of a user, the LoginSubscriptionManagerService implementation calls the onLogin() function of all its subscribers.

The onLogin() method requires two parameters to be passed:

  • configRegistry: Provides access to registry resource properties and allows registry operations. Examples: accessing the metadata of the resource at a given path, creating a resource by fetching the resource content from the given URL, renaming a resource in the registry, moving a resource in the registry, copying a resource in the registry etc.  
  • LoginEvent: Allows you to access data related to the logged in user (Example: username, tenantID, tenant domain).

Using the basic model explained above, you can implement the login functionality for your requirement. A sample implementation of an OSGi bundle that implements the LoginListener API is given below.

Implementing LoginListener API

In this implementation, you are logging a message with the following details: username, tenantID and tenant domain of the user logged in to the management console of your Carbon product. The LoginSubscriptionManagerService interface allows components to subscribe a callback that can be called when a user login happens. The LogMessageListener interface is the implementation that I am using to implement the LoginListener interface. In the following, the onLogin() method is implemented and event data from LoginEvent is used for the log message. 

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.core.services.callback.LoginListener;
import org.wso2.carbon.core.services.callback.LoginEvent;
import org.wso2.carbon.registry.core.Registry;

/**
* Implementing Login-Listener from core.services.
*/
public class LogMessageListener implements LoginListener {
   private static final Log log = LogFactory.getLog(LogMessageListener.class);

   public void onLogin(Registry configRegistry, LoginEvent event) {
       LoginEvent loginEvent = event;

       log.info("Logged in user : " + loginEvent.getUsername() + " with tenant ID " + loginEvent.getTenantId()
               + " with tenant domain : " + loginEvent.getTenantDomain());
       
       //this registry variable contains APIs which control 
       // tags/comments/ratings/versions/etc.

       Registry registry = configRegistry;
   }
}

The LogMessageServiceComponent class is an OSGi service component that is used for subscribing to LoginListener. The activate() method does not include any major logic. The LoginSubscriptionManagerService class is used as a reference and the set-unset methods are added accordingly. A new instance of LoginListener is implemented, which subscribes to the LoginSubscriptionManagerService in the setLoginSubscriptionManagerService() method.

loginManager.subscribe(new LogMessageListner());

This allows you to subscribe the LogMessageListner() to LoginSubscriptionManagerService during bundle activation time.

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.*;
import org.wso2.carbon.core.services.callback.LoginSubscriptionManagerService;
import org.wso2.carbon.login.sample.listener.LogMessageListner;

@Component(name = "sample.core.services.logcomponent", immediate = true)
public class LogMessageServiceComponent {
   private static Log log = LogFactory.getLog(LogMessageServiceComponent.class);
   private static BundleContext bundleContext;

   @Activate
   protected void activate(ComponentContext context) {
       bundleContext = context.getBundleContext();
   }

   @Reference(
           name = "login.subscription.service",
           service = org.wso2.carbon.core.services.callback.LoginSubscriptionManagerService.class,
           cardinality = ReferenceCardinality.MANDATORY,
           policy = ReferencePolicy.DYNAMIC,
           unbind = "unsetLoginSubscriptionManagerService"
   )
   protected void setLoginSubscriptionManagerService(LoginSubscriptionManagerService loginManager) {
       log.debug("******* LoginSubscriptionManagerServic is set ******* ");
       loginManager.subscribe(new LogMessageListner());
   }

   protected void unsetLoginSubscriptionManagerService(LoginSubscriptionManagerService loginManager) {
       log.debug("******* LoginSubscriptionManagerServic is unset ******* ");
   }

   protected void deactivate(ComponentContext ctxt) {
       LogMessageServiceComponent.bundleContext = null;
       log.debug("Carbon Core Services bundle is deactivated ");
   }
}

Shown below is the pom.xml of the OSGi bundle. I have added a bundle activator class, which does not perform any complex logic. Please find the required maven dependencies given below.

 <?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/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>org.wso2.carbon</groupId>
   <artifactId>org.wso2.carbon.login.sample</artifactId>
   <version>1.0.0-SNAPSHOT</version>
   <packaging>bundle</packaging>
   <name>WSO2 Carbon - Samples</name>
   <url>http://wso2.org</url>

   <pluginRepositories>
       <pluginRepository>
           <id>wso2-nexus</id>
           <name>WSO2 internal Repository</name>
           <url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>
           <releases>
               <enabled>true</enabled>
               <updatePolicy>daily</updatePolicy>
               <checksumPolicy>ignore</checksumPolicy>
           </releases>
       </pluginRepository>
   </pluginRepositories>

   <dependencies>
       ...
       <dependency>
   <groupId>org.wso2.carbon</groupId>
   <artifactId>org.wso2.carbon.core.services</artifactId>
   <version>${core.version}</version>
</dependency>
   </dependencies>

   <build>
       <plugins>
           <plugin>
               <groupId>org.apache.felix</groupId>
               <artifactId>maven-scr-plugin</artifactId>
              <executions>
                  <execution>
                      <id>generate-scr-scrdescriptor</id>
                      <goals>
                          <goal>scr</goal>
                      </goals>
                  </execution>
              </executions>
           </plugin>
           <plugin>
               <groupId>org.apache.felix</groupId>
               <artifactId>maven-bundle-plugin</artifactId>
               <extensions>true</extensions>
               <configuration>
                   <instructions>
                       <Bundle-Vendor>WSO2 Inc</Bundle-Vendor>
                       <Bundle-SymbolicName>org.wso2.carbon.login.sample</Bundle-SymbolicName>
                       <Bundle-Name>org.wso2.carbon.login.sample</Bundle-Name>
                       <Private-Package>org.wso2.carbon.login.sample.internal</Private-Package>
                       <Bundle-Version>1.0.0</Bundle-Version>
                       <Bundle-Activator>org.wso2.carbon.login.sample.activator.LoginBundleActivator</Bundle-Activator>
                       <Import-Package>
                           org.osgi.framework, org.wso2.carbon.core.services.callback.*,
                           *;resolution:=optional
                       </Import-Package>
                       <Export-Package>org.wso2.carbon.login.sample.activator*,
                           org.wso2.carbon.login.sample.listener.*
                       </Export-Package>
                       <DynamicImport-Package>*</DynamicImport-Package>
                   </instructions>
               </configuration>
           </plugin>
       </plugins>
   </build>
</project>

After building the sample above, you can add your OSGi bundle to the <PRODUCT_HOME>/repository/components/dropins directory and start the Carbon server. Try logging in to the management console and you should see a log message as follows:

INFO {org.wso2.carbon.login.sample.listener.LogMessageListner} -  Logged in user : admin with tenant ID -1234 with tenant domain : carbon.super

You can write your own custom logic that need to be invoked when a user login happens.

com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links2' is unknown.