This article gives insights on how an EJB session bean must be created and then invoked by the OBIEE action framework.
@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";
}
..........
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;
.........
<?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.
The registry entry defines where to find the Session Bean with the help of a lookup where:
See this article for a complete JNDI lookup example on Weblogic. J2EE - EJB Remote Client with Eclipse OEPE on Weblogic (Outside the container).
The content type node contains standard definitions and parameters for action framework and must be contain once in the configuration file
The account node defines the account that will call the EJB where:
gives the location of the credential created in the Credential Store
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:
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.
The ejb-app > server node from the registry have a DNS name that is not known, not accessible of simply not good.