Soa 11g has an Identity web service which you can use to retrieve your Human Workflow Groups and Users. In this Blog I will show you how you can use this identity service to add users and groups with their managers ( build a hierarchy ) without the need of an expensive Directory server. In the Human Task you can use this hierarchy for Task Escalation and these groups and users can also be used for the Human Task owner or assignee. Basically the identity service will return all the users and groups of the myrealm weblogic security realm. Too bad building this hierarchy is not possible in the Weblogic Console or Enterprise Manager website.
When you have an LDAP server like Oracle Internet Directory or Active Directory you can use this for the Human workflow groups and users. Make sure that the control type of all the authenticators has the SUFFICIENT value and that is LDAP is the first server in the Authentication providers.
So the first step is to retrieve all the Human Task groups & users. For this we need to call the Identity web service, this WS only runs on the Weblogic soa_server1 server ( so we need to connect to port 8001 and no authorization is required). This information can't be retrieved from the Human Task EJB and the security realm is always jazn.com or just leave it empty.
package nl.whitehorses.soa.human.workflow;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import oracle.bpel.services.workflow.client.IWorkflowServiceClientConstants;
import oracle.bpel.services.workflow.client.WorkflowServiceClientFactory;
import oracle.tip.pc.services.identity.BPMGroup;
import oracle.tip.pc.services.identity.BPMIdentityException;
import oracle.tip.pc.services.identity.BPMIdentityService;
import oracle.tip.pc.services.identity.BPMUser;
public class WorkflowGroupUser {
private String wsurl = "http://localhost:8001";
private String secdomain = "jazn.com";
private BPMIdentityService bpmClient;
private Logger logger = Logger.getLogger(WorkflowGroupUser.class.getName());
public WorkflowGroupUser() {
Map<IWorkflowServiceClientConstants.CONNECTION_PROPERTY, java.lang.String> properties =
new HashMap<IWorkflowServiceClientConstants.CONNECTION_PROPERTY, java.lang.String>();
properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.SOAP_END_POINT_ROOT, wsurl);
bpmClient = WorkflowServiceClientFactory.getSOAPIdentityServiceClient(secdomain,
properties,
logger);
}
public List<BPMGroup> getGroups() throws BPMIdentityException {
List<BPMGroup> groups = bpmClient.searchGroups("name", "*");
return groups;
}
public List<BPMUser> getUsers() throws BPMIdentityException {
List<BPMUser> users = bpmClient.searchUsers("name", "*");
return users;
}
public static void main(String[] args) {
WorkflowGroupUser workflowGroupUser = new WorkflowGroupUser();
try {
for (BPMGroup group : workflowGroupUser.getGroups()) {
System.out.println("groups: " + group.getDisplayName());
}
for (BPMUser user : workflowGroupUser.getUsers()) {
System.out.println("users: " + user.getDisplayName()+" manager " +user.getManager());
}
} catch (BPMIdentityException e) {
e.printStackTrace();
}
}
}
For Security reasons I need to make a Servlet or EJB Session Bean and deploy this to the Weblogic soa server ( not the admin server ). In this Servlet or EJB Session Bean we can retrieve IdentityConfigService and initialize the IdentityStore. In this blog I choose for an EJB Session Bean.
package nl.whitehorses.soa.human.workflow.model;
import java.util.List;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import oracle.security.idm.IMException;
import oracle.security.idm.IdentityStore;
import oracle.security.idm.Property;
import oracle.security.idm.PropertySet;
import oracle.security.idm.Role;
import oracle.security.idm.RoleManager;
import oracle.security.idm.RoleProfile;
import oracle.security.idm.User;
import oracle.security.idm.UserManager;
import oracle.security.idm.UserProfile;
import oracle.tip.pc.services.common.ServiceFactory;
import oracle.tip.pc.services.identity.BPMIdentityException;
import oracle.tip.pc.services.identity.config.BPMIdentityConfigService;
import oracle.tip.pc.services.identity.config.ProviderCfg;
import oracle.tip.pc.services.identity.jps.JpsProvider;
@Stateless(name = "HumanWorkFlowEJB", mappedName = "HumanWorkFlowEJB")
@Remote
public class HumanWorkFlowEJBBean implements HumanWorkFlowEJB {
private BPMIdentityConfigService bpmConfig;
private IdentityStore identityStore;
public HumanWorkFlowEJBBean() throws BPMIdentityException, Exception {
bpmConfig = ServiceFactory.getIdentityConfigServiceInstance();
String realmName = bpmConfig.getDefaultRealmName();
ProviderCfg conf = bpmConfig.getConfiguration(realmName).getProviderCfg("Authorization");
JpsProvider provider = (JpsProvider)JpsProvider.getInstance(conf);
identityStore = provider.getIdentityStore();
System.out.println("default realm: " + realmName);
}
public void addUser(String name, String email,
String manager) throws IMException {
UserManager usrmgr = identityStore.getUserManager();
User user = null;
try {
user = identityStore.searchUser(name);
} catch (IMException e) {
}
if (user != null) {
System.out.println("user " + name + " exists");
} else {
PropertySet pset = new PropertySet();
pset.put(new Property("DESCRIPTION", name));
pset.put(new Property("USER_NAME", name));
pset.put(new Property("USER_ID", name));
char pwd[] = "weblogic".toCharArray();
user = usrmgr.createUser(name, pwd, pset);
user = identityStore.searchUser(user.getName());
UserProfile up = user.getUserProfile();
if ( email != null ) {
up.setBusinessEmail(email);
}
if ( manager != null ) {
User userManager = null;
try {
userManager = identityStore.searchUser(manager);
} catch (IMException ie) {
}
if (manager != null) {
up.setManager(userManager.getUniqueName());
}
}
}
}
public void addGroup(String group,
List<String> members) throws IMException {
RoleManager rolemgr = identityStore.getRoleManager();
Role role = null;
try {
role = identityStore.searchRole(1, group);
} catch (IMException e) {
}
if (role == null) {
role = rolemgr.createRole(group);
}
RoleProfile rolePrf = role.getRoleProfile();
if (members != null && members.size() > 0) {
for (int m = 0; m < members.size(); m++) {
User user = null;
try {
user = identityStore.searchUser((String)members.get(m));
} catch (IMException e) {
}
if (user != null) {
rolemgr.grantRole(role, user.getPrincipal());
}
}
}
}
public void removeUser(String user) throws Exception {
UserManager usrmgr = identityStore.getUserManager();
if (user != null) {
User idtyUser = null;
try {
idtyUser = identityStore.searchUser(user);
} catch (IMException e) {
}
if (idtyUser != null) {
usrmgr.dropUser(idtyUser);
}
}
}
public void removeGroup(String role) throws Exception {
RoleManager rolemgr = identityStore.getRoleManager();
Role idtyRole = null;
try {
idtyRole = identityStore.searchRole(1, role);
} catch (IMException e) {
}
if (idtyRole != null) {
rolemgr.dropRole(idtyRole);
}
}
}
And the Remote interface of this EJB Session Bean.
package nl.whitehorses.soa.human.workflow.model;
import java.util.List;
import javax.ejb.Remote;
import oracle.security.idm.IMException;
@Remote
public interface HumanWorkFlowEJB {
public void removeGroup(String role) throws Exception;
public void removeUser(String user) throws Exception;
public void addGroup(String group, List<String> members) throws IMException;
public void addUser(String name, String email,String manager) throws IMException;
}
This EJB Session needs the bpm-services.jar located in the following folder Soa11gPS1\Oracle_SOA1\soa\modules\oracle.soa.workflow_11.1.1\bpm-services.jar
Add this jar as a library in Weblogic, use the name bpm-services and make sure it is targeted on the soa server and not the admin server.
Add the bpm-services library reference to the weblogic-application.xml deployment descriptor. this file will be added to the META-INF of the ear deployment.
<?xml version = '1.0' encoding = 'windows-1252'?>
<weblogic-application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bea.com/ns/weblogic/weblogic-application http://www.bea.com/ns/weblogic/weblogic-application/1.0/weblogic-application.xsd"
xmlns="http://www.bea.com/ns/weblogic/weblogic-application">
<library-ref>
<library-name>bpm-services</library-name>
</library-ref>
</weblogic-application>
Deploy the EJB Session Bean to the Soa server and not to the Admin server.
After this we can add some users with their managers. I will use this EJB test client for this( connect to the SoaSuite server ( port 8001) not the Admin server
package nl.whitehorses.soa.human.workflow;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import nl.whitehorses.soa.human.workflow.model.HumanWorkFlowEJB;
public class HumanWorkFlowEJBClient {
public static void main(String [] args) {
try {
final Context context = getInitialContext();
HumanWorkFlowEJB humanWorkFlowEJB = (HumanWorkFlowEJB)context.lookup("HumanWorkFlowEJB#nl.whitehorses.soa.human.workflow.model.HumanWorkFlowEJB");
humanWorkFlowEJB.addUser("admin1", "admin1@wh.nl", null);
humanWorkFlowEJB.addUser("admin3", "admin3@wh.nl", "admin1");
List<String> members = new ArrayList();
members.add("admin3");
members.add("admin1");
humanWorkFlowEJB.addGroup("App-MHS-Admin_2", members);
} catch (Exception ex) {
ex.printStackTrace();
}
}
private static Context getInitialContext() throws NamingException {
Hashtable env = new Hashtable();
// WebLogic Server 10.x connection details
env.put( Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory" );
env.put(Context.PROVIDER_URL, "t3://localhost:8001");
return new InitialContext( env );
}
}
These Human Taks users & groups are normal Weblogic users & groups and are visible in the Weblogic Security Realm ( Weblogic Console ).