Who created that Site Studio section?

question was asked today on the Oracle WebCenter Content forum about how to determine the user who created a Site Studio section.

Hi All, is it possible to get the user details about one section, like who has created that section in site hierarchy

Out of the box, Site Studio does not appear to store the user name of the person who created a section. If this information were to be found, we would expect to find it in the XML project file. However, upon examination of a newly created section, there is no mention of the user who created that section.

<section label=”456″ nodeId=”23″ urlDirName=”456″/>

This issue can be solved but to do so, a custom component is needed. Site Studio sections are created via the service SS_ADD_NODE. This service calls the addNode method. There is a filterSiteStudioAddNode, that is fired at the end of the addNode method. At first, my thought was to use similar code to addNode (and the other methods it calls) to add/set an attribute on the newly created section. However, most of this code is in methods with protected or no modifier. This makes it difficult (but not impossible) to gain access to those methods. Even if that code were easily accessible, a better approach is to call the Site Studio service SS_SET_NODE_PROPERTY at the end of the SiteStudioAddNode filter.

  • Description: This service sets a node property.
  • Parameters:
    • siteId: the unique identifier of the site (required).
    • nodeId: the unique identifier of the node (required).
    • property: the name of the property to set or remove (required).
    • value: the new value of the attribute (optional). If the value is not specified, the property will be removed.
  • Returns: Nothing.
  • Security: The user must have at least write access to the node.

This service will do everything we need and if Oracle decides to change their code, our code keeps working because we are simply calling a service. The parameters needed for this service call are in the filter’s DataBinder. The new section’s nodeId is in the DataBinder as the parameter newNodeId. The property parameter is the name of the attribute we want to set. For this, I created a preference prompt, SSSectionCreatedBy_PropertyName, which contains the attribute name (by default, the preference prompt value is createdBy). The value attribute, is the current user. This can be retrieved from the ExecutionContext which can be cast to a Service object since we are in a filter. I have made the component, [download id=”10″], available for download. Below, you can find the Java filter code to implement the functionality of storing the user who created a section. This same approach to building a component can be applied to add other information (such as a security related information) to a newly created section node in the project file. Once the component is installed and enabled, adding a new section will result in similar information being added to the project file (notice the createdBy attribute).

<section createdBy=”sysadmin” label=”456″ nodeId=”23″ urlDirName=”456″/>

This createdBy property can be retrieved by calling the service SS_GET_NODE_PROPERTY with parameters siteIdnodeId and property (where property is the attribute name set in the preference prompt). The value is returned in the LocalData as value. You can also retrieve the createdBy property using the Idoc Script function ssGetNodeProperty (pass in the parameters nodeId and name, where name is the attribute name set in the preference prompt).

package com.jonathanhult.webcenter.content.sssectioncreatedby;

import static com.jonathanhult.webcenter.content.sssectioncreatedby.SSSectionCreatedByConstants.COMPONENT_ENABLED;
import static com.jonathanhult.webcenter.content.sssectioncreatedby.SSSectionCreatedByConstants.D_NAME;
import static com.jonathanhult.webcenter.content.sssectioncreatedby.SSSectionCreatedByConstants.IDC_SERVICE;
import static com.jonathanhult.webcenter.content.sssectioncreatedby.SSSectionCreatedByConstants.NEW_NODE_ID;
import static com.jonathanhult.webcenter.content.sssectioncreatedby.SSSectionCreatedByConstants.NODE_ID;
import static com.jonathanhult.webcenter.content.sssectioncreatedby.SSSectionCreatedByConstants.PROPERTY;
import static com.jonathanhult.webcenter.content.sssectioncreatedby.SSSectionCreatedByConstants.PROPERTY_NAME;
import static com.jonathanhult.webcenter.content.sssectioncreatedby.SSSectionCreatedByConstants.SITE_ID;
import static com.jonathanhult.webcenter.content.sssectioncreatedby.SSSectionCreatedByConstants.SS_SET_NODE_PROPERTY;
import static com.jonathanhult.webcenter.content.sssectioncreatedby.SSSectionCreatedByConstants.TRACE_SECTION;
import static com.jonathanhult.webcenter.content.sssectioncreatedby.SSSectionCreatedByConstants.VALUE;
import static intradoc.shared.SharedObjects.getEnvValueAsBoolean;
import static intradoc.shared.SharedObjects.getEnvironmentValue;
import intradoc.common.ExecutionContext;
import intradoc.common.Report;
import intradoc.common.ServiceException;
import intradoc.data.DataBinder;
import intradoc.data.DataException;
import intradoc.data.Workspace;
import intradoc.server.Service;
import intradoc.shared.FilterImplementor;
import intradoc.shared.UserData;

/**
 * @author Jonathan Hult
 * [email protected] https://jonathanhult.com}
 */
public class SiteStudioAddNodeFilter implements FilterImplementor {

	private static UserData m_userData;
	private static String m_userName;

	/**
	 * This method implements a SiteStudioAddNode filter for the SSSectionCreatedBy component.
	 * First, it checks to determine whether the component is enabled by the preference prompt SSSectionCreatedBy_ComponentEnabled.
	 * Second, it finds the current user who is adding a section.
	 * Third, it calls the service SS_SET_NODE_PROPERTY.
	 * This service sets the user name as the value for the attribute name defined in the preference prompt SSSectionCreatedBy_PropertyName.
	 */
	public int doFilter(final Workspace ws, final DataBinder binder, final ExecutionContext ctx) throws DataException, ServiceException {
		trace("Start doFilter for SiteStudioAddNode for SSSectionCreatedBy");

		try {
			// Exit if component is not enabled
			if (!getEnvValueAsBoolean(COMPONENT_ENABLED, false)) {
				trace("Component not enabled");
				return CONTINUE;
			}

			// DataBinder to execute service SS_SET_NODE_PROPERTY
			final DataBinder serviceBinder = new DataBinder();

			// Get siteId
			final String siteId = binder.getLocal(SITE_ID);

			// Get nodeId
			final String nodeId = binder.getLocal(NEW_NODE_ID);

			// Put necessary service parameters into serviceBinder
			serviceBinder.putLocal(SITE_ID, siteId);
			serviceBinder.putLocal(NODE_ID, nodeId);
			serviceBinder.putLocal(PROPERTY, getEnvironmentValue(PROPERTY_NAME));
			serviceBinder.putLocal(VALUE, getUserName((Service)ctx));

			// Execute SS_SET_NODE_PROPERTY service
			executeService(serviceBinder, (Service)ctx, SS_SET_NODE_PROPERTY);

			return CONTINUE;
		} finally {
			trace("End doFilter for SiteStudioAddNode for SSSectionCreatedBy");
		}
	}

	/**
	 * This method executes a service.
	 * @param serviceBinder The DataBinder which contains information about the service call.
	 * @param service The Service from the original service call.
	 * @param serviceName The name of the Service from to execute.
	 * @throws ServiceException
	 */
	public static void executeService(final DataBinder serviceBinder, final Service service, final String serviceName) throws ServiceException {
		traceVerbose("Start executeService");

		// Put service name to execute in serviceBinder
		serviceBinder.putLocal(IDC_SERVICE, serviceName);
		try {
			trace("Calling service " + serviceName + ": " + serviceBinder.getLocalData().toString());
			// Execute service
			service.getRequestImplementor().executeServiceTopLevelSimple(serviceBinder, serviceName, getUserData(service));
			trace("Finished calling service");
		} catch (final DataException e) {
			trace("Something went wrong executing service " + serviceName);
			e.printStackTrace(System.out);
			throw new ServiceException("Something went wrong executing service " + serviceName, e);
		} finally {
			traceVerbose("End executeService");
		}
	}

	/**
	 * This method retrieves the UserData from the ExecutionContext/Service.
	 * @param The Service from ExecutionContext.
	 * @return UserData for current service user.
	 */
	public static UserData getUserData(final Service service) {
		traceVerbose("Start getUserData");

		try {
			if (m_userData != null) {
				return m_userData;
			}
			// Retrieve UserData
			m_userData = service.getUserData();

			// Retrieve User name
			m_userName = m_userData.getProperty(D_NAME);
			trace("Username: " + m_userName);

			return m_userData;
		} finally {
			traceVerbose("End getUserData");
		}
	}

	/**
	 * This method retrieves the current user name from the ExecutionContext/Service.
	 * @param The Service from ExecutionContext.
	 * @return User name for current service user.
	 */
	public static String getUserName(final Service service) {
		traceVerbose("Start getUserName");

		try {
			if (m_userName != null) {
				return m_userName;
			}

			// Get UserData
			getUserData(service);

			// User name will now be available
			return m_userName;

		} finally {
			traceVerbose("End getUserName");
		}
	}

	/**
	 * This methods traces output to the WebCenter Content console.
	 * @param message The String to trace to the WebCenter Content console.
	 */
	public static void trace(final String message) {
		Report.trace(TRACE_SECTION, message, null);
	}

	/**
	 * This method verbose traces output to the WebCenter Content console.
	 * @param message The String to trace to the WebCenter Content console.
	 */
	public static void traceVerbose(final String message) {
		if (Report.m_verbose) {
			trace(message);
		}
	}
}
package com.jonathanhult.webcenter.content.sssectioncreatedby;

/**
 * @author Jonathan Hult
 * [email protected] https://jonathanhult.com}
 */
public class SSSectionCreatedByConstants {
	public static final String IDC_SERVICE = "IdcService";
	public static final String SS_SET_NODE_PROPERTY = "SS_SET_NODE_PROPERTY";
	public static final String SITE_ID = "siteId";
	public static final String NODE_ID = "nodeId";
	public static final String NEW_NODE_ID = "newNodeId";
	public static final String PROPERTY = "property";
	public static final String PROPERTY_NAME = "SSSectionCreatedBy_PropertyName";
	public static final String VALUE = "value";
	public static final String D_NAME = "dName";
	public static final String TRACE_SECTION = "sssectioncreatedby";
	public static final String COMPONENT_ENABLED = "SSSectionCreatedBy_ComponentEnabled";
}

Leave a Reply

2 Comments on "Who created that Site Studio section?"

Notify of
avatar
Sort by:   newest | oldest | most voted
Romain
Guest

Thanks for this very instructing article!
Where do I find the list of all filters (SiteStudioAddNode.. etc) that are fired by UCM or SSXA?
Also how do you created the component, especially SSSectionCreatedBy.hda? Is there a tool for that?

wpDiscuz