OBIEE 11G - Action Framework - How to create and invoke a Java Method (EJB)

> Reporting and Data Access Tools > Oracle Business Intelligence (OBIEE/Siebel Analytics) > OBIEE - BI Presentation Service (SAW/OBIPS)

1 - About

This article gives insights on how an EJB session bean must be created and then invoked by the OBIEE action framework.

Advertising

3 - Steps

3.1 - Creation of the EJB

3.1.1 - Definition

  • JNDI Location: Action Framework expects EJBs to be deployed to the default location of /ejb. The mappedName annotation of the Session bean must preceded by a ejb/
  • Binary document: In order to send documents, the Java method should include a specific Java data type (javax.activation.DataHandler) as a parameter.
@Stateless(name = "myEjb", mappedName = "ejb/myEjb")
public class myEjb
        implements myEjbLocal, myEjbRemote
{
 
        public String ArchiveReport(String filename,
			javax.activation.DataHandler report) throws FileNotFoundException, IOException {
 
		File f = new File(filename);
		FileOutputStream outputStream = new FileOutputStream(f);
		report.writeTo(outputStream);
		outputStream.close();
 
		return "Report Archived";
	}
..........

3.1.2 - Remote interface parameters

The Action Framework finds the Java methods exposed through the remote interface of the EJB. The parameters of exposed methods become the parameters for an action.

Note the import statement for oracle.bi.action.annotation.OBIActionParameter to support the annotation @OBIActionParameter which allows you to specify parameter name and prompt value to display when creating an action in OBIEE.

package nl.hotitem.ejb;
import javax.ejb.Remote;
import oracle.bi.action.annotation.OBIActionParameter;
 
@Remote
public interface myEjbRemote
{
 
    void sayOnlyHello(
    		@OBIActionParameter (name = "Name", prompt = "Enter your name:") 
    		String name);
 
    String ArchiveReport(
		@OBIActionParameter(name = "Filename", prompt = "Enter filename location:") String filename,
		@OBIActionParameter(name = "Analysis", prompt = "Report to Archive:") DataHandler document)
			throws FileNotFoundException, IOException;
.........

3.2 - Configuration of Action Framework

3.2.1 - Complete Minimum Configuration file

<FMW_HOME>\user_projects\domains\bifoundation_domain\config\fmwconfig\biinstances\coreapplication\ActionFrameworkConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<obi-action-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="afconfig.xsd">
	<registries>
		<registry>
			<id>reg01</id>
			<name>Sample EJBs</name>
			<content-type>java</content-type>
			<provider-class>oracle.bi.action.registry.java.EJBRegistry</provider-class>
			<description>Custom Java classes which can be invoked as action targets</description>
			<location>
				<path/>
			</location>
			<custom-config>
				<ejb-targets>
					<appserver>
						<context-factory>weblogic.jndi.WLInitialContextFactory</context-factory>
						<jndi-url>t3://localhost:7001</jndi-url>
						<server-name>localhost</server-name>
						<account>WLSJNDI</account>
						<ejb-exclude>mgmt</ejb-exclude>
						<ejb-exclude>PopulationServiceBean</ejb-exclude>
					</appserver>
					<ejb-app>
						<server>localhost</server>
						<app-context>ActionSamplesEJB</app-context>
					</ejb-app>
				</ejb-targets>
			</custom-config>
		</registry>
	</registries>
	<content-types>
		<content-type>
			<typename>java</typename>
			<displayname>Java Actions</displayname>
			<actionType>JavaActionType</actionType>
		</content-type>
	</content-types>
	<accounts>
		<account>
			<name>WLSJNDI</name>
			<description>Account used to access WLS JNDI.</description>
			<adminonly>false</adminonly>
			<credentialkey>JNDIUser</credentialkey>
			<credentialmap>oracle.bi.actions</credentialmap>
		</account>
	</accounts>
</obi-action-config>

where the node definition are explain below.

After each change in this configuration file, a restart of the managed server is needed.

Advertising

3.2.2 - Node

3.2.2.1 - Registry

The registry entry defines where to find the Session Bean with the help of a lookup where:

  • the id must be unique
  • the name must be unique
  • the content-type must be always java and refers to the content-types > content type node in the same configuration file
  • the provider class must have as value: oracle.bi.action.registry.java.EJBRegistry
  • the context factory must have as value: weblogic.jndi.WLInitialContextFactory
  • the account node refers to the accounts > account node in the same configuration file
  • the ejb-app > server must points to the correct server hosting the EJB
  • the ejb-app > context is just a contextual information

See this article for a complete JNDI lookup example on Weblogic. J2EE - EJB Remote Client with Eclipse OEPE on Weblogic (Outside the container).

3.2.2.2 - Content-type

The content type node contains standard definitions and parameters for action framework and must be contain once in the configuration file

3.2.2.3 - Account

The account node defines the account that will call the EJB where:

  • credentialkey
  • and credentialmap

gives the location of the credential created in the Credential Store

Advertising

4 - Invokation

5 - Support

5.1 - [Security:090398] Invalid Subject

When attempting to read the EJB in the Web front-end, you may receive this error:

The fault reported was: 
[Security:090398] Invalid Subject: principals=[weblogic, Administrators]

In the log, you may also find:

Message	** errorDiscoveringEJBs**
Supplemental Detail	javax.naming.CommunicationException 
[Root exception is java.rmi.UnmarshalException: Problem finding error class; nested exception is: 
java.lang.ClassNotFoundException: nl.hotitem.ejb.HotStarsEjbRemote]
at weblogic.jndi.internal.ExceptionTranslator.toNamingException(ExceptionTranslator.java:74)
at weblogic.jndi.internal.WLContextImpl.translateException(WLContextImpl.java:470)
at weblogic.jndi.internal.WLContextImpl.list(WLContextImpl.java:237)
at javax.naming.InitialContext.list(InitialContext.java:436)
at oracle.bi.action.registry.java.EJBRegistry.recurseJNDITree(EJBRegistry.java:281)
at oracle.bi.action.registry.java.EJBRegistry.recurseJNDITree(EJBRegistry.java:287)
at oracle.bi.action.registry.java.EJBRegistry.recurseJNDITree(EJBRegistry.java:287)
at oracle.bi.action.registry.java.EJBRegistry.recurseJNDITree(EJBRegistry.java:287)
at oracle.bi.action.registry.java.EJBRegistry.findEJBNodes(EJBRegistry.java:209)

This error Security:090398 is the error BEA-090398

BEA-090398: Invalid Subject: {0}
Cause: Principal validation failed for this subject.
Action: Ensure that subject was created by this domain or in a domain trusted by this domain.
Level: 1
Type: ERROR
Impact: Security

The call of the EJB remote interface is done through RMI and with a little search on the oracle support web site, we get this article: RMI Exception when Connecting Two Domains: java.lang.SecurityException: [Security:090398]Invalid Subject.

The problem comes from that the EJB called are not in the same domain. There is a security mechanism which prevents two domains without configuration to speak each other.

The solutions are:

5.2 - Error finding J2EE app

You may receive this error:

Gerapporteerde fout: 
Error finding J2EE app Hotstars at JNDI url t3://localhost:7001/Hotstars

It can be caused by the fact that the registry name in the XML configuration file is not unique.

5.3 - Error Reading Credential

The ejb-app > server node from the registry have a DNS name that is not known, not accessible of simply not good.