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 ).
sorry but i dont think this sample very useful...
ReplyDeleteYou are stressing to only deploy to the SOA server and not the Admin Server. Why is that? Does the IdentityService not work on the AdminServer?
ReplyDeleteHi,
ReplyDeletethere is no identity service on the adminServer. So it won't work. In PS3 you can do a developer install of SOA Suite where everything is on the adminserver. This is the exception to this.
thanks
Edwin - thanks for the prompt reply. Ok, that is how we are setup in non-prod environments (using PS3), with everything on a single server. But for some reason, our identity service is not 'finding' LDAP users in those environments but does when we have the SOA server broken out. The ADProvider is setup identically in either environment. So I was wondering if there was a limitation of the IdentityService to use LDAP if it were running within the AdminServer.
ReplyDeleteI'll continue to research.
Thanks!
Hi,
ReplyDeleteI think they did this to reduce the memory consumption, you need to find the ear on the soa server which does the identity service and add it manually on your adminserver. then you can connect to this EJB / WS.
thanks
Hello,
ReplyDeleteI need to create a user task where the user can searck for users and groups, and then select some of them.
I already saw this kind of functionality in many out of the box features in workspace (for instance, identity browse makes something like this) or in the reassign task page on the reassing option in workspace, this really does what Im looking for).
So my question is: can I get and customize any of this standard pages? Or do I need to create one? If I need to create one, do I need to create such a logic to search ldap like you show here?
thank you,
nep
Hi,
ReplyDeleteyep, you need to create your own page and query the users / groups
like in this blogs code.
public List getGroups()
public List getUsers()
this will call the identity service.
then you can do what you want.
thanks
Hello,
ReplyDeletethank you for your answer.
the component I was talking about is IdentityBrowser. Have you sure I cant reuse it? Because it does actually that kind of search. The unique problem is that I would need to overwrite the listner of the ok button to control the process (dont know if it is possible)?
thank you again
Hi,
ReplyDeleteI am able to get bpmAppRole and also the users.Is there any way I can map users to bpmaAppRoles like we do in bpm workspace.In workspace under administration we click on bpmAppRole and add users to it.Can we do the same thing using java api.
Thanks
Edwin, Could you share any link or details on Integrating an existing Custom Application(Wrapper application over Oracle-HR security Hierarchy) with Oracle Identity Service for workflow assignment?
ReplyDeleteEdwin, Could you share any link or details on Integrating an existing Custom Application(Wrapper application over Oracle-HR security Hierarchy) with Oracle Identity Service for workflow assignment?
ReplyDeleteThanks
Hi Edwin,
ReplyDeleteI am having little trouble with running custom client as webapp. I followed your steps and tested in as an console app and it is working fine. But If I try to run it in debug mode with jdeveloper's embedded server it is returning me no class def found. Any hints?
Hi,
ReplyDeleteI think I saw that error once, do you have a stacktrace.
thanks
Hi Edwin,
ReplyDeleteyour blog is a great source of valuable information, thank you for sharing!
Now, i've made a custom client thanks to your hints. All works fine, except app-roles retrieval.
It works if unit tested, or deploying the client app on tomcat, but fails when the app is deployed on a second domain of soa-suite wls. (i can't deploy my gui-app on the same domain of soa-suite because i've used richfaces that clashes with adf library).
I get this error: "ERR: ORABPEL-10585 Errore di servizio. Errore interno: errore di servizio in BPMIdentityService nel metodo getGrantedRolesToUser. Vedere il file di log configurato per oracle.soa.services.identity"
Sorry it's in italian, it fails inkoking the method: getGrantedRolesToUser.
I can't find anything on server logs...
Googling i found that this error code is likely associated to misconfiguration on /etc/hosts but this is not the case, i checked.
Any idea?
Thanks in advance.
Hi,
DeleteFor the roles it connects to the identity ws located on the soa suite server
that is this var private String wsurl = "http://localhost:8001";
I think you opss is not configured or can't connect to this ws or it tries to use the authenticated user in tomcat which is not known in soa domain.
can you not add a managed wls server to the soa domain which has not adf lib target to this server. then you don't have security problems when you authenticate.
thanks
Hi Sir
ReplyDeleteI face problem regarding to integrate P6 and BPM
ORABPEL-10585
BPM service could not connect to BPM Identity service provider for database
could you help me ?
Hi,
DeleteOPSS only works great with LDAP servers and use virtualize property for extra authenticators or add this as first authenticator and put all provider control flag on sufficient.
thanks
Edwin do you know where is configure the users'manager in the weblogic console, or jazn file. I find Attributes but not he hierarchy.
ReplyDeleteThanks in advance.
Hi,
Deleteit is located in the weblogic LDAP , you can use a ldap client to connect to the weblogic ldap and change it there.
you can follow this http://technology.amis.nl/2013/02/05/21036/
Thanks
Edwin,
ReplyDeleteI am getting java.lang.NoSuchMethodError: javax.wsdl.Definition.getAllPortTypes()Ljava/util/Map
while invoking searchUser method . Weblogic is integrated with ActiveDirectory. I am getting BPMdentityService in standlone java .
Thanks
Never mind , added orawsdl.jar file , it worked .Thanks
ReplyDeleteHi Edwin,
ReplyDeleteI am getting an error while when I click on the user name link at the top left corner on the BPM Worklist application on Oracle SOA Suite 11.1.1.7. An empty user info pops up. I am using a custom security provider plugin to validate the users and it works fine. But clicking on the link throws an exception. My weblogic has two servers; one admin and the other is a managed soa server. I haven't configured OPSS as well. I came to know from Oracle support that OPSS may be required for multiple server domain environments. Is that really the case? Could you please help in this matter?
Exception Stacktrace below:
Refer to the log file that is configured for oracle.soa.services.identity for more details on this error and contact Oracle Support Services
".
Ensure that the soap message is properly formed and has all necessary attributes and elements. Contact Oracle Support Services if error is not fixable.
ORABPEL-10592
Identity Service soap error.
BPMIdentityService encountered soap error in method invoke with fault "Service error.
Internal Error; Service error occurs in UserImpl in method populateDetails().
Refer to the log file that is configured for oracle.soa.services.identity for more details on this error and contact Oracle Support Services
".
Ensure that the soap message is properly formed and has all necessary attributes and elements. Contact Oracle Support Services if error is not fixable.
at oracle.bpel.services.identity.client.IdentityServiceSOAPClient.convertSOAPFaultException(IdentityServiceSOAPClient.java:249)
at oracle.bpel.services.identity.client.IdentityServiceSOAPClient.invoke(IdentityServiceSOAPClient.java:214)
at oracle.bpel.services.identity.client.IdentityServiceSOAPClient.lookupUser(IdentityServiceSOAPClient.java:287)
at oracle.bpel.services.identity.client.AbstractIdentityServiceClient.lookupUser(AbstractIdentityServiceClient.java:187)
at oracle.bpel.worklistapp.util.WorklistUtil.getCurrentUser(WorklistUtil.java:641)
at oracle.bpel.worklistapp.beans.view.HomePageView.getUserDisplayName(HomePageView.java:140)
at oracle.bpel.worklistapp.beans.view.HomePageView.getCurrentUser(HomePageView.java:128)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.el.BeanELResolver.getValue(BeanELResolver.java:293)
at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:173)
at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:200)
at com.sun.el.parser.AstValue.getValue(AstValue.java:138)
at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:206)
at org.apache.myfaces.trinidad.bean.FacesBeanImpl.getProperty(FacesBeanImpl.java:68)
at oracle.adfinternal.view.faces.renderkit.rich.GoLinkRenderer.getText(GoLinkRenderer.java:526)
at oracle.adfinternal.view.faces.renderkit.rich.GoLinkRenderer.encodeAll(GoLinkRenderer.java:123)
at oracle.adfinternal.view.faces.renderkit.rich.CommandLinkRenderer.encodeAll(CommandLinkRenderer.java:158)
at oracle.adfinternal.view.faces.renderkit.rich.CommandNavigationItemRenderer.encodeAll(CommandNavigationItemRenderer.java:144)
at oracle.adfinternal.view.faces.renderkit.rich.NavigationPaneRenderer$NavigationPaneItemRenderer.renderItem(NavigationPaneRenderer.java:2056)