Search code examples
javaweblogicjmx

Creating WebLogic users programmatically from a standalone Java client


I'm trying to create users in WebLogic (10.3.4) programmatically from a simple standalone Java client (one class --> two methods: createWeblogicUser() & main()).

public void createWeblogicUser() {
try {
    Hashtable<String, String> env = new Hashtable<String, String>();
    env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
    env.put(Context.SECURITY_PRINCIPAL, "weblogic");
    env.put(Context.SECURITY_CREDENTIALS, "weblogic");
    env.put(Context.PROVIDER_URL, "t3://myserver:7001");

    InitialContext ctx = new InitialContext(env);
    MBeanServer wls = (MBeanServer) ctx.lookup("java:comp/env/jmx/runtime");

    ObjectName userEditor = null;
    ObjectName mBeanTypeService = new ObjectName( "com.bea:Name=MBeanTypeService, Type=weblogic.management.mbeanservers.MBeanTypeService");
    ObjectName rs = new ObjectName("com.bea:Name=RuntimeService, Type=weblogic.management.mbeanservers.runtime.RuntimeServiceMBean");
    ObjectName domainMBean = (ObjectName) wls.getAttribute(rs, "DomainConfiguration");
    ObjectName securityConfig = (ObjectName) wls.getAttribute(domainMBean, "SecurityConfiguration");
    ObjectName defaultRealm = (ObjectName) wls.getAttribute(securityConfig, "DefaultRealm");
    ObjectName[] authProviders = (ObjectName[]) wls.getAttribute(defaultRealm, "AuthenticationProviders");

    for(ObjectName providerName : authProviders) {
        if(userEditor == null) {
            ModelMBeanInfo info = (ModelMBeanInfo) wls.getMBeanInfo(providerName);
            String className = (String) info.getMBeanDescriptor().getFieldValue("interfaceClassName");
            if(className != null) {
                String[] mba = (String[]) wls.invoke(mBeanTypeService
                                                    , "getSubtypes"
                                                    , new Object[] {"weblogic.management.security.authentication.UserEditorMBean"}
                                                    , new String[] {"java.lang.String"}
                                            );
                for(String mb : mba) {
                    if(className.equals(mb))
                        userEditor = providerName;
                }
            }
        }

        if(userEditor == null)
            throw new RuntimeException("Could not retrieve user editor");

        try {
            wls.invoke(userEditor
                        , "createUser"
                        , new Object[] {"wls_user", "password123","User created programmatically."}
                        , new String[] {"java.lang.String", "java.lang.String","java.lang.String"}
            );
        }
        catch(Exception e){
            e.printStackTrace();
        }

        ctx.close();
    }
}
catch(Exception ex) {
    ex.printStackTrace();
}

}

Any ideas on what the context lookup I should be making? "java:comp" throws a javax.naming.NameNotFoundException; looks like I can use that only from w/in a container.


Solution

  • Got it to work.

    private void createWeblogicUser(String username) {
    try {
        Hashtable<String, String> env = new Hashtable<String, String>();
        env.put(Context.SECURITY_PRINCIPAL, "weblogic");
        env.put(Context.SECURITY_CREDENTIALS, "weblogic");
    
        String hostname = "myserver";
        int port = 7001;
        String protocol = "rmi";
        String url= new String("/jndi/iiop://myserver:7001/weblogic.management.mbeanservers.domainruntime");
    
        JMXServiceURL serviceURL = new JMXServiceURL(protocol, hostname, port, url);
        JMXConnector connector = JMXConnectorFactory.connect(serviceURL, env);
        MBeanServerConnection connection = connector.getMBeanServerConnection();
    
        ObjectName userEditor = null;
        ObjectName mBeanTypeService = new ObjectName( "com.bea:Name=MBeanTypeService,Type=weblogic.management.mbeanservers.MBeanTypeService");
        ObjectName rs = new ObjectName("com.bea:Name=DomainRuntimeService,Type=weblogic.management.mbeanservers.domainruntime.DomainRuntimeServiceMBean");
        ObjectName domainMBean = (ObjectName) connection.getAttribute(rs, "DomainConfiguration");
        ObjectName securityConfig = (ObjectName) connection.getAttribute(domainMBean, "SecurityConfiguration");
        ObjectName defaultRealm = (ObjectName) connection.getAttribute(securityConfig, "DefaultRealm");
        ObjectName[] authProviders = (ObjectName[]) connection.getAttribute(defaultRealm, "AuthenticationProviders");
    
        for(ObjectName providerName : authProviders) {
            System.out.println("Auth provider is: " + providerName) ;
    
            if(userEditor == null) {
                ModelMBeanInfo info = (ModelMBeanInfo) connection.getMBeanInfo(providerName);
                String className = (String) info.getMBeanDescriptor().getFieldValue("interfaceClassName");
                System.out.println("className is: " + className) ;
    
                if(className != null) {
                    String[] mba = (String[]) connection.invoke(mBeanTypeService
                                            , "getSubtypes"
                                            , new Object[] {"weblogic.management.security.authentication.UserEditorMBean"}
                                            , new String[] {"java.lang.String"}
                                        );
                    for(String mb : mba) {
                        System.out.println("Model Bean is: " + mb) ;
                        if(className.equals(mb)) {
                            System.out.println("Found a macth for the model bean and class name!") ;
                            userEditor = providerName;
                        }
                    }
                }
            }
        }
    
        if(userEditor == null)
            throw new RuntimeException("Could not retrieve user editor");
    
        try {
            connection.invoke(userEditor
                        , "createUser"
                        , new Object[] {username, "password123","User created programmatically."}
                        , new String[] {"java.lang.String", "java.lang.String","java.lang.String"}
            );
    
            System.out.println("User created successfully") ;
        }
        catch(Exception e){
            e.printStackTrace();
        }
    
        connector.close();
    
    }
    catch(Exception ex) {
        ex.printStacktrace();
    }
    

    }

    You need only weblogic.jar and wljmxclient.jar in classpath. I ran this against JDK 1.6.0_29. I have to add that I ran this on a machine on which WebLogic was installed as well. So the classpath entries were fully qualified path names to the jar files.

    One "gotcha" I came across: While providing the "com.bea:Name=XXXX,Type=XXXX", DONOT give a space between anything - not the colon; not the comma; nothing - I spent sometime debugging this, before it finally hit it.