« November 2007 | Main | January 2008 »

December 2007 Archives

December 5, 2007

Asynchronous Servlet Article Extras - Push Events

This was originally posted on my dev2dev blog December 5th, 2007.

I just finished reading Francesco Marchioni's article entitled Using Asynchronous Servlets to Deal with Hung Threads and thought that I could add some information for those that want to explore this functionality more and see a working example of a chat room built with AJAX.  This is really about implementing virtual push event to web clients.  Starting with WLS 10, there is an out-of-the-box example that ships with WebLogic Server that illustrates using the Abstract Asynchronous Servlet to build a chat room.  In effect, it uses AJAX to create an event push (via a long poll).  So now when a client sends a message to the chat room, all the clients receive the message virtually instantly without constantly polling the server for new messages.  This technique has come to be known as Comet in AJAX terminology.  To read the details of the example, just go to <BEA_HOME>/wlserver_10.0/samples/server/docs/core/index.html and expand the tree as shown below.  To run it, just follow the directions which are very straight-forward.

ChatExample

Also check the javadoc for the AbstractAsynchrounousServlet to get more information about the API.

One neat thing to do is to run the example with both Firefox and IE at the same time and see messages sent by the IE client show up immediately in the Firefox client.  I have the Firebug plug-in installed and you can see how the XmlHttpRequest (XHR) is waiting for new chat messages to come in.  If no new messages arrive in 20 seconds, the AbstractAsynchServlet times out the request.  Then the client issues a new XHR and starts the process again.

firefoxWithFirebug

I've seen some fairly neat examples and demos built with the AbstractAsynchronousServlet in WebLogic Portal such as a dash-board portlet that sends out messages and alerts.  So if you have use-cases that would benefit from having events virtually pushed to web clients, consider using this approach as it is very effective and does not tie up threads on the server.

December 13, 2007

Using LDAP as a user-store for WebLogic Administrators

This was originally posted on my dev2dev blog December 13th, 2007.   Edited on 11/19/2008 based on feedback from a customer to add clarity for control flags in the authentication providers.

One of my customers that has hundreds of WLS instances recently asked me about moving towards a centralized model for managing WebLogic Administrators.  Currently they use the file-based out-of-the-box embedded LDAP that ships with WebLogic Server as an Administrator store.  This is great for getting started quickly, but it means that each instance has it's own local user store for Administrators.  Therefore, when one of their Administrators leaves the company they have to go to each server and change the Administrator password.  Now that can be a headache!  I have previously posted on how to set up WebLogic Server for use with OpenLDAP so that LDAP users can be used for authentication for web apps, etc.  In this post, I'll discuss how to extend that to WebLogic Administration, so that centralized administration of WebLogic Administrators can be enabled via external LDAP.

Review the documentation for Authentication Providers

E-docs has some great detail on how to configure more than one Authentication Provider and how to configure LDAP Authentication Providers, and specifically addresses the case in which LDAP is the only Authentication Provider.  One thing that is important to highlight if you go down the path of only having LDAP as the sole Authentication Provider is that it introduces a point of failure into your WebLogic Servers, meaning that if your WLS instances get network partitioned from your LDAP server(s) or your LDAP server(s) goes down, your WLS instances will not boot.  You can partially guard against this by configuring LDAP fail-over, but to keep the flexibility, you may want to keep the Default Authenticator around for emergencies and keep that user/password isolated to a master Administrator.  There are two ways to enable someone to be a WebLogic Administrator:

  1. Add the user to the Administrators group in LDAP (which is included in the Admin global role by default)
  2. Add the user to the Admin global role (you can do this by group, explicit user, etc)

As it is mentioned in the docs, your LDAP may already use the Administrators group for another purpose, or you may not want to put users in that group and give them Administrator access to all the domains in your environment.  In this case, the 2nd method allows you to be much more granular and even put users in groups that might correlate to their business unit.  So I could have an HRWebLogicAdmins group in LDAP for the Human Resources department, and when I create the domains for that department, make sure I add that group to the Admin Global Role.  If that approach is taken, users may be able to use their normal LDAP user and credentials instead of a special Administrative account that is shared because their personal user has group membership to HRWebLogicAdmins.  This provides you with an additional level of auditing since you are not using shared Administrator accounts.

Configure your base domain

Let's put this into practice.  First let's assume were starting from scratch with no domains at all.  We'll configure LDAP with it and confirm that we can have Administrators in LDAP, then create a domain template with LDAP preconfigured so that new domains don't have to do this LDAP setup at all.  I'm going to use WLS 10 MP1 for this, but the steps should be similar in other versions of WLS.  I'm using the same OpenLDAP configuration that I discussed in my previous post, so refer to that for more detail on this setup if you need it.

  1. Create a domain - D:\bea100MP1\wlserver_10.0\common\bin\config.cmd (sh)
  2. Keep the defaults, which will have weblogic/weblogic as your Administrator.
  3. Start the AdminServer and login with weblogic/weblogic.at http://localhost:7001/console
  4. Click the "Lock & Edit" button in the console and optionally then click the "Record" button if you are in WLS 10 or higher and want to record the WLST script
  5. Add the OpenLDAP Authenticator to your realm.  Remember to set the control flag of both the Default Authenticator and your LDAP Authenticator to OPTIONAL or SUFFICENT.  If you leave the control flag setting as is for the Default Authenticator, which is REQUIRED, then any user authenticating in the realm would need to be in embedded LDAP also, which is not what we want.  Restarting the server will be required for the security changes to take effect, even if the console doesn't remind you, so don't forget that step.
  6. Review the Admin role mapping to see that it maps to the users/groups you want.  In this example, I'm assuming that the using the Adminstrators group in LDAP is okay.

Roles [2]

Here is the default mapping for all users in the Admin role.  Notice that it includes all of the users in the Adminstrators group by default.  This is where I could add other groups.  Be aware that role changes you make are stored as XACML and have to be imported/exported.

groupMapping

Now click "Activate Changes" and notice the name of the WLST script if you did a recording and the notice that we need to restart the server for the changes to take affect since we modified the security subsystem.  At this point we can shut the server down.

Now let's review my LDAP configuration.  Using JXplorer I can both view and edit my OpenLDAP configuration.  Here are the settings that work with the LDAP config from my previous post:  Note that the password is "secret".

jxplorer

Note that I added an Administrators group and added the jbayer user as a member of that group.  To add a group, just right click on "groups" and select "New" and go through the prompts.

Explorer

Ok, now I should be able to boot WLS with the jbayer user and login to the console as an Administrator.  Let's try both.  First I need to update the boot.properties file that is located in the domain's <Server_Name>/security directory.  In my case, that is:  D:\bea100MP1\user_projects\domains\open_ldap_domain3\servers\AdminServer\security

Opening the file shows you that the username and password are encrypted, so now we need to replace the {3DES} encrypted values with plain text ones for my jbayer user.  The next time WLS boots, it will re-encrypt these values.  Note that we can also find out the domains encrypted values ourselves by using the encryption utility:

D:\bea100MP1\user_projects\domains\open_ldap_domain3\bin>setDomainEnv.cmd

D:\bea100MP1\user_projects\domains\open_ldap_domain3>java weblogic.security.Encrypt jbayer
{3DES}yunUy+yVmfY=

D:\bea100MP1\user_projects\domains\open_ldap_domain3>java weblogic.security.Encrypt weblogic
{3DES}PmZxnuL1akG6MzWSRo/g3w==


Now we can boot the domain.  If there is a problem, you'll see a stack trace that mentions the security sub-system, you'll probably have to change the boot.properties file back to the original values, weblogic/weblogic if you didn't change the defaults and see if you messed up anywhere.
 
If there is no problem and the server goes to a RUNNING state, then we have booted the server as jbayer, which is in the Admin role because that user is in the Administrators group in OpenLDAP.  Now try logging into the console and that should work as well.  Here is my screen-shot showing the successful jbayer user login as Administrator to the console.
jbayer [2]

Make it repeatable with WLST or a Domain Template

Doing all of this configuration each time you want to setup a new domain can monotonous and prone to typing mistakes.  This is where using WLST or domain templates can come in very handy.  First let's review the .py file that was created during our WLST recording as we created the OpenLDAP Authenticator.  Mine was saved to my domain's base directory with the name Script1197502551016.py.  For more on WLST see my intro to WLST post and the command reference for documentation on WLST commands.

cd('/SecurityConfiguration/open_ldap_domain/Realms/myrealm')
cmo.createAuthenticationProvider('openLdapAuthenticator', 'weblogic.security.providers.authentication.OpenLDAPAuthenticator')

cd('/SecurityConfiguration/open_ldap_domain/Realms/myrealm/AuthenticationProviders/openLdapAuthenticator')
cmo.setGroupBaseDN('ou=groups, dc=bea, dc=com')
cmo.setStaticGroupObjectClass('groupOfNames')
cmo.setUserBaseDN('ou=people, dc=bea, dc=com')
cmo.setUserObjectClass('inetOrgPerson')
cmo.setPrincipal('cn=Manager,dc=bea,dc=com')
setEncrypted('Credential', 'Credential_1197503008359', 'D:/bea100MP1/user_projects/domains/open_ldap_domain/Script1197502551016Config', 'D:/bea100MP1/user_projects/domains/open_ldap_domain/Script1197502551016Secret')
cmo.setStaticGroupDNsfromMemberDNFilter('(&(member=%M)(objectclass=groupOfNames))')
cmo.setUserFromNameFilter('(&(cn=%u)(objectclass=inetOrgPerson))')
cmo.setGroupFromNameFilter('(&(cn=%g)(objectclass=groupOfNames))')
cmo.setControlFlag('SUFFICIENT')

cd('/SecurityConfiguration/open_ldap_domain/Realms/myrealm/AuthenticationProviders/DefaultAuthenticator')
cmo.setControlFlag('SUFFICIENT')

activate()


I could simply use a script like this to configure my new domains to have LDAP support after they have been created.  However, I can go one step further and use the domain that has already been configured for LDAP and create a domain template using the Domain Template Builder D:\bea100MP1\wlserver_10.0\common\bin\config_builder.cmd.  Now when I create new Domains using the Config Wizard and base it off that template, authentication to OpenLDAP will be pre-configured.  Just launch the Domain Template Wizard, point it at the domain and follow all of the defaults.  I can even configure the Admin Role here to include other groups.

One Last Gotcha

One big gotcha that I encountered is that the new domains that I created based off that template still had the OpenLDAP password for the manager user set to the encrypted value of the first domain in the config.xml file in the new domain's config directory.  Each domain has a unique way of encrypting it's passwords so the encrypted values cannot be exchanged between domains.  I've highlighted the incorrect value below in the credential-encrypted element.  Make sure you replace that value with new domains correct {3DES} value that you can retrieve with technique illustrated earlier: java weblogic.security.Encrypt password.  I'm investigating whether this is working as designed or not as I expected the Config Wizard to take care of that for me. 

<sec:authentication-provider xsi:type="wls:open-ldap-authenticatorType">
  <sec:name>openLdapAuthenticator</sec:name>
  <sec:control-flag>SUFFICIENT</sec:control-flag>
  <wls:propagate-cause-for-login-exception>false</wls:propagate-cause-for-login-exception>
  <wls:user-object-class>inetOrgPerson</wls:user-object-class>
  <wls:principal>cn=Manager,dc=bea,dc=com</wls:principal>
  <wls:user-base-dn>ou=people, dc=bea, dc=com</wls:user-base-dn>
  <wls:credential-encrypted>{3DES}68bCeqro3EA=</wls:credential-encrypted>
  <wls:user-from-name-filter>(&amp;(cn=%u)(objectclass=inetOrgPerson))</wls:user-from-name-filter>
  <wls:group-base-dn>ou=groups, dc=bea, dc=com</wls:group-base-dn>
  <wls:group-from-name-filter>(&amp;(cn=%g)(objectclass=groupOfNames))</wls:group-from-name-filter>
  <wls:static-group-object-class>groupOfNames</wls:static-group-object-class>
  <wls:static-group-dns-from-member-dn-filter>(&amp;(member=%M)(objectclass=groupOfNames))</wls:static-group-dns-from-member-dn-filter>
</sec:authentication-provider>

Hopefully this illustrates how LDAP can provide a way to manage WebLogic Administration in a way that is more scalable than having individual user stores in embedded LDAP when many WLS instances are involved.

December 21, 2007

Using Workshop 10.1 with WebLogic Server 10.0 MP1

This was originally posted on my dev2dev blog December 21st, 2007 but should now be considered obsolete now that Workshop 10.2 is released and the Oracle Eclipse Pack will be released soon.

Background

Workshop for WebLogic 10.1 ships with WebLogic Server 10.0 GA bundled in the installer.  Since that time BEA has released Maintenance Pack 1 for WLS 10.0.  So when one of my customers was getting started with developing on WebLogic Server 10.0, I recommended that they start with Server 10.0 MP1 because it has about 7 months worth of bug fixes that the 10.0 GA bits don't have.  Now this customer also wanted to take advantage of all of the great features that first showed up in Workshop 10.1, such as JSF, JPA, Hibernate, Struts, Spring, Beehive tooling all nicely assembled in Eclipse.  After talking with Workshop product management, I realized that there are no plans to update the Workshop 10.1 installer to include the WebLogic Server 10.0 MP1 bits.  You can still use Workshop 10.1 to deploy to Server 10.0 MP1, but there are some caveats.

Expectation:  I should just be able to update the WebLogic Server 10.0 GA instance to MP1 by using SmartUpdate.  Theoretically yes, but not in this case.  The WebLogic Server 10.0 GA bits that are included with the default Workshop 10.1 installation are there just to support Workshop and are not able to be upgraded because Workshop 10.1 has not been updated itself for MP1.

Disclaimer:  Note that this configuration (deploying from Workshop 10.1 to Server 10.0 MP1) has not been explicitly tested by our support teams.  I've found most use-cases work just fine.  I've noted several gotchas below, but be aware that this has not gone through an extensive QA.

The installation steps

Workshop 10.1 Installer

Choose the "complete" installation.

*Updated 12/21/07* Do not choose the custom installation!  Choose "Complete".  It turns out that Workshop 10.1 does have dependences on the Server 10.0 GA bits, so it's best to leave the defaults selected and install both Workshop 10.1 and Server 10.0 GA into the same BEA Home.  You can still install Server 10.0 MP1 into a different BEA Home without its Workshop 10.0 MP1 components as I show further below.  One of the things that will not work if Workshop 10.1 is installed without Server 10.0 GA in its BEA Home is deploying an application with EJBs to WebLogic Server from Workshop.  Reference CR356168 with BEA Support if you encounter troubles in this regard.

complete

 

Now install Server 10.0 MP1 into a new BEA_HOME directory.

Select the custom installation, and make sure you install into a separate BEA_HOME directory from Workshop 10.1.

server1

Deselect the Workshop 10.0 components if you do not plan on using Workshop 10.0 MP1, but it doesn't harm anything other than take up disk space if you leave it selected.

server2

Post-installation Configuration

At this point, I recommend changing the default JVM that Workshop will use to be the more recent Sun JDK that ships with Server 10 MP1.  I'll address this later, but it follows from the infamous serialVersionUID bug that has been around in the Sun JVM for awhile.  Open Workshop's ini file (mine is D:\Workshop10.1\workshop_10.1\workshop4WP\workshop4WP.ini) and point it to the updated JDK.

Before:

-vm D:/Workshop10.1/jdk150_06/jre/bin/javaw.exe

etc, etc.

After:

-vm D:/bea100MP1/jdk150_11/jre/bin/javaw.exe

etc, etc.

Now you'll have both Workshop 10.1 and Server 10 MP1 installed on your machine, the next step is to configure Workshop 10.1 so that it is aware of the Server 10 runtime.  Go ahead and open a workspace and select Window->Preferences...->Server->Installed Runtimes.  Delete the existing 10.0 GA runtime and add the runtime for WebLogic Server 10 MP1.  Normally I wouldn't have to do this step, but since we installed Workshop and Server separately we have to tell Workshop where to find Server and where the correct library modules are located.

runtime

After we set that we should see that WebLogic->J2EE Libraries is now populated with the 10.0 MP1 libraries:

Note:  If you did not delete the 10.0 GA runtime, you'll see multiple copies of the libraries.  They are actually unique, which you can tell by highlighting one, clicking the edit button and noting that the implementation version is different, even though the specification version is the same.

libraries

Now we're all set to develop and deploy as normal.  If you forgot to switch your JVM to the version that ships with WLS 10 MP1, which is jdk150_11, you will probably encounter the serialVersionUID error when you work with Beehive Service Controls.  Here is a a look at what that stack might look like, so you know to switch the JVM, delete your types-jar file from WEB-INF/lib, rebuild your controls in Workshop and then redeploy if you encounter it.

<Dec 14, 2007 1:26:32 PM CST> <Error> <com.bea.control.servicecontrol.util.memento.ServiceClassMementoUtil> <BEA-000000>

<com.bea.control.servicecontrol.util.memento.ServiceClassMementoUtil: Could not load the ServiceClassMemento from the following resource file:

control/EchoServiceControlServiceClassMemento.ser.

This is probably due to a versioning issue and if the developer was astute when they made the change then this should not be the reason. Another

possibility is that this resource has become corrupt. The good news is a rebuild of your app should fix it.

Throwable: java.io.InvalidClassException: javax.xml.namespace.QName; local class incompatible: stream classdesc serialVersionUID =

4418622981026545151, local class serialVersionUID = -9120448754896609940
Stack Trace:
java.io.InvalidClassException: javax.xml.namespace.QName; local class incompatible: stream classdesc serialVersionUID =

4418622981026545151, local class serialVersionUID = -9120448754896609940
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:546)


About December 2007

This page contains all entries posted to James Bayer's Blog in December 2007. They are listed from oldest to newest.

November 2007 is the previous archive.

January 2008 is the next archive.

Many more can be found on the main index page or by looking through the archives.

Powered by
Movable Type and Oracle