Unified User Profile (UUP) in Weblogic Portal
Attached is everything you need I think.
To Learn the theoretical part please refer following link
http://e-docs.bea.com/wlp/docs100/users/uup.html
Let get to practical, Here’s the basic steps to get this running :
1. Add a Data Source to your domain with the JNDI name "dizzyworld.dizzyDataSource"
2. Run Following SQL script on the corresponding DB
CREATE TABLE weblogic.CUSTOMER_PROFILE (USER_NAME VARCHAR(20) NOT NULL,AGE INTEGER,EMAIL VARCHAR(30),STATUS VARCHAR(30),CATEGORY VARCHAR(30));
ALTER TABLE weblogic.CUSTOMER_PROFILE ADD CONSTRAINT DIZZY_PROFILE PRIMARY KEY (USER_NAME);
INSERT INTO weblogic.CUSTOMER_PROFILE (USER_NAME) VALUES('weblogic');
INSERT INTO weblogic.CUSTOMER_PROFILE (USER_NAME) VALUES('portaladmin');
3. Add USR file to your Datasync project
DizzyCustomer
USER
Age
The customer's age
false
false
Integer
Email
The customer's email address
false
false
Text
Status
The customer's status
false
false
Text
Category
The type of customer
false
false
Text
4. Add a WebLogic EJB Project to your EAR named "DizzyUUP"
5. Add Following EJB source file to the EJB project
package com.dizzyworld.profile;
import java.rmi.RemoteException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.ejb.CreateException;
import javax.ejb.SessionBean;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import com.bea.p13n.cache.Cache;
import com.bea.p13n.cache.CacheFactory;
import com.bea.p13n.property.ConfigurableEntityCreateException;
import com.bea.p13n.property.ConfigurableEntitySystemException;
import com.bea.p13n.property.EntityNotFoundException;
import com.bea.p13n.property.EntityPropertyCache;
import com.bea.p13n.property.PropertyLocator;
import com.bea.p13n.property.PropertyMapKey;
import com.bea.p13n.property.PropertyValidationException;
import com.bea.p13n.property.internal.EntityPropertyCacheImpl;
import com.bea.p13n.property.internal.PropertyMapKeyImpl;
import weblogic.ejb.GenericSessionBean;
import weblogic.ejbgen.Session;
import weblogic.ejbgen.JndiName;
import weblogic.ejbgen.FileGeneration;
import weblogic.ejbgen.Constants;
import weblogic.ejbgen.RemoteMethod;
import weblogic.ejbgen.ResourceRefs;
import weblogic.ejbgen.ResourceRef;
/**
* A UUP is implemented by providing your own EntityPropertyManager EJB
* implementation class. This EJB is registered with the ProfileManager in the
* ProfileManager's EJB deployment descriptor. The ProfileManager is, in turn,
* registered with the UserManager EJB.
*
* This EntityPropertyManager manages user properties found in a custom database
* table. This table is accessed using the dizzyDataSource.
*/
@Session(ejbName = "MyEntityPropertyManager", defaultTransaction = Constants.TransactionAttribute.NOT_SUPPORTED)
@JndiName(remote = "dizzyworld.MyEntityPropertyManager")
@FileGeneration(remoteClass = Constants.Bool.TRUE, remoteHome = Constants.Bool.TRUE, localClass = Constants.Bool.FALSE, localHome = Constants.Bool.FALSE)
@ResourceRefs(value = { @ResourceRef(name = "jdbc/dizzyDataSource", type = "javax.sql.DataSource", auth = ResourceRef.Auth.CONTAINER, jndiName = "dizzyworld.dizzyDataSource") })
public class MyEntityPropertyManager extends GenericSessionBean implements
SessionBean {
private static final long serialVersionUID = 1L;
/**
* Cache name used to obtain the application-wide cache from the
* CacheFactory. Configure and manage this cache through the portal admin
* console.
*/
protected static final String PROPERTY_CACHE_NAME = "DizzyUUPCache";
protected static final boolean USE_CACHE = false;
/**
* Profile propery names Must match the names used in the property set
* definition (.usr)
*/
protected static final String AGE_PROPERTY = "Age";
protected static final String EMAIL_PROPERTY = "Email";
protected static final String STATUS_PROPERTY = "Status";
protected static final String CATEGORY_PROPERTY = "Category";
/**
* The name of the database table containing profile data
*/
protected static final String TABLE_NAME = "weblogic.CUSTOMER_PROFILE";
/**
* SQL string used to create the PreparedStatement for retrieving all
* properties for a given user. This schema only supports single valued
* properties.
*/
protected static final String SELECT_PROPERTIES_STATEMENT = "SELECT AGE,EMAIL,STATUS,CATEGORY FROM "
+ TABLE_NAME + " WHERE USER_NAME = ?";
/**
* SQL string used to create the PreparedStatement for removing all
* properties for a given user.
*/
protected static final String REMOVE_PROPERTIES_STATEMENT = "UPDATE "
+ TABLE_NAME
+ " SET AGE = NULL, SET EMAIL = NULL, SET STATUS = NULL, SET CATEGORY = NULL WHERE USER_NAME = ?";
/**
* SQL string used to create the PreparedStatement for removing a single
* given property for a given user.
*/
protected static final String REMOVE_PROPERTY_STATEMENT_1 = "UPDATE "
+ TABLE_NAME + " SET ";
protected static final String REMOVE_PROPERTY_STATEMENT_2 = " = NULL WHERE USER_NAME = ?";
/**
* SQL string used to create the PreparedStatement for removing a given user
* and all of their properties.
*/
protected static final String REMOVE_ENTITY_STATEMENT = "DELETE FROM "
+ TABLE_NAME + " WHERE USER_NAME = ?";
/**
* SQL string used to create the PreparedStatement for setting a given
* property for a given user.
*/
protected static final String SET_PROPERTY_STATEMENT_1 = "UPDATE "
+ TABLE_NAME + " SET ";
protected static final String SET_PROPERTY_STATEMENT_2 = " = ? WHERE USER_NAME = ?";
/**
* SQL string used to create the PreparedStatement for creating a new user.
*/
protected static final String CREATE_ENTITY_STATEMENT = "INSERT INTO "
+ TABLE_NAME + " (USER_NAME) VALUES(?)";
/**
* Name for the DataSource specified in the
*/
protected static final String DATA_SOURCE = "jdbc/dizzyDataSource";
/**
* ejbCreate method
*/
public void ejbCreate() throws CreateException {
// do nothing
}
/**
* Returns an EntityPropertyCache containing all properties that are
* persisted for the given user, as identified with a PropertyLocator.
*
* @param locator
* a PropertyLocator that identifies the user entity
* @return a populated EntityPropertyCache
* @exception EntityNotFoundException
* if the user entity identified by the property locator does
* not exist
*/
@RemoteMethod()
public EntityPropertyCache getProperties(PropertyLocator locator)
throws EntityNotFoundException {
Connection connection = null;
PreparedStatement selectStatement = null;
ResultSet resultSet = null;
EntityPropertyCache propertyCache = null;
// Check the cache first.
propertyCache = getItemFromCache(locator);
if (propertyCache != null) {
return propertyCache;
}
/*
* The cache did not contain properties for this user so get the
* properties from the database.
*/
propertyCache = new EntityPropertyCacheImpl();
boolean userExists = false;
try {
// Get a database connection.
connection = getConnection();
// SELECT to find all the properties associated with the user
String userName = locator.getPkString();
selectStatement = connection
.prepareStatement(SELECT_PROPERTIES_STATEMENT);
selectStatement.setString(1, userName);
resultSet = selectStatement.executeQuery();
while (resultSet.next()) {
userExists = true;
Integer age = resultSet.getInt(1);
String email = resultSet.getString(2);
String status = resultSet.getString(3);
String category = resultSet.getString(4);
/*
* Cache the properties. The
* com.bea.p13n.property.PropertyMapKey is a lightweight key for
* the property name and property set name. The
* com.bea.p13n.internal.property.PropertyMapKeyImpl class
* implements the PropertyMapKey interface.
*/
if (age != null) {
PropertyMapKey propertyMapKey = new PropertyMapKeyImpl(
null, AGE_PROPERTY);
propertyCache.put(propertyMapKey, age);
}
if (email != null) {
PropertyMapKey propertyMapKey = new PropertyMapKeyImpl(
null, EMAIL_PROPERTY);
propertyCache.put(propertyMapKey, email);
}
if (status != null) {
PropertyMapKey propertyMapKey = new PropertyMapKeyImpl(
null, STATUS_PROPERTY);
propertyCache.put(propertyMapKey, status);
}
if (category != null) {
PropertyMapKey propertyMapKey = new PropertyMapKeyImpl(
null, CATEGORY_PROPERTY);
propertyCache.put(propertyMapKey, category);
}
}
} catch (SQLException sqle) {
throw new ConfigurableEntitySystemException(sqle);
} finally {
try {
resultSet.close();
} catch (Exception e) {
}
try {
selectStatement.close();
} catch (Exception e) {
}
try {
connection.close();
} catch (Exception e) {
}
}
if (userExists) {
/*
* Put the whole entity value cache into the application-wide cache.
*/
addItemToCache(locator, propertyCache);
return propertyCache;
} else {
throw new EntityNotFoundException(locator.getPkString()
+ " does not exist");
}
}
/**
* Returns the value of the property defined for the specified property and
* property set.
*
* If the property does not have a value persisted, then null is returned.
*
* @param locator
* a PropertyLocator identifying the user entity to look up
* @param propertySet
* the name of the property set
* @param propertyName
* the name of the property
* @return the property's value, or null if there is none
* @exception EntityNotFoundException
* if the entity identified by the property locator does not
* exist
*/
@RemoteMethod()
public Object getProperty(PropertyLocator locator, String propertySetName,
String propertyName) throws EntityNotFoundException {
/*
* Use getProperties() to check cache, get from database if not in
* cache. The EntityPropertyCache is the container used to keep all user
* properties in the application-wide cache.
*/
EntityPropertyCache epc = getProperties(locator);
PropertyMapKey propertyMapKey = new PropertyMapKeyImpl(null,
propertyName);
return epc.get(propertyMapKey);
}
/**
* Removes all property values associated with the user entity specified by
* the property locator. After a property value is removed for a user
* entity, subsequent calls to getProperty() must return null for that user
* entity, notifying the property search algorithm to move on to the
* successors.
*
* @param locator
* a PropertyLocator identifying the user entity to modify
* @exception EntityNotFoundException
* if the user entity identified by the property locator does
* not exist
*/
@RemoteMethod()
public void removeProperties(PropertyLocator locator)
throws EntityNotFoundException {
Connection conn = null;
PreparedStatement removePropertiesStatement = null;
try {
conn = getConnection();
removePropertiesStatement = conn
.prepareStatement(REMOVE_PROPERTIES_STATEMENT);
// The userName is in the PropertyLocator's pkString
removePropertiesStatement.setString(1, locator.getPkString());
int affectedRowCount = removePropertiesStatement.executeUpdate();
if (affectedRowCount == 0) {
throw new EntityNotFoundException(locator.getPkString()
+ " does not exist");
}
// Remove the properties from the cache
removeItemFromCache(locator);
} catch (SQLException sqle) {
throw new ConfigurableEntitySystemException(sqle);
} finally {
try {
removePropertiesStatement.close();
} catch (Exception e) {
}
try {
conn.close();
} catch (Exception e) {
}
}
}
/**
* Removes a specific property value from the user entity specified by the
* property locator. After a property value is removed for a user entity,
* subsequent calls to getProperty() must return null for that user entity,
* notifying the property search algorithm to move on to the successors.
*
* @param locator
* a PropertyLocator identifying the user entity to modify
* @param propertySet
* the property set containing the property to remove
* @param propertyName
* the name of the property to remove
* @return The old value of the property, if any
* @exception EntityNotFoundException
* if the entity identified by the property locator does not
* exist
*/
@RemoteMethod()
public Object removeProperty(PropertyLocator locator,
String propertySetName, String propertyName)
throws EntityNotFoundException {
// Get the current value
Object oldValue = getProperty(locator, propertySetName, propertyName);
if (oldValue != null) {
Connection conn = null;
PreparedStatement removePropertyStatement = null;
try {
conn = getConnection();
// Set the column name to clear
removePropertyStatement = conn
.prepareStatement(REMOVE_PROPERTY_STATEMENT_1 + propertyName.toUpperCase() + REMOVE_PROPERTY_STATEMENT_2);
// The userName is in the PropertyLocator's pkString
removePropertyStatement.setString(1, locator.getPkString());
int affectedRowCount = removePropertyStatement.executeUpdate();
if (affectedRowCount == 0) {
throw new EntityNotFoundException(locator.getPkString()
+ " does not exist");
}
// Remove it from the cache.
PropertyMapKey propertyMapKey = new PropertyMapKeyImpl(null,
propertyName);
removeCachedPropertyValue(locator, propertyMapKey);
} catch (SQLException sqle) {
throw new ConfigurableEntitySystemException(sqle);
} finally {
try {
removePropertyStatement.close();
} catch (Exception e) {
}
try {
conn.close();
} catch (Exception e) {
}
}
}
return oldValue;
}
/**
* Sets the property identified by the given property set and property name
* to the given value for the user entity specified by the given property
* locator.
*
* @param locator
* a PropertyLocator identifying the user entity to modify
* @param propertySet
* the property set containing the property to modify
* @param propertyName
* the name of the property to modify
* @param value
* the value to persist for the given property and user entity
* @exception PropertyValidationException
* if the value is not valid for the given property
* @exception EntityNotFoundException
* if the entity identified by the property locator does not
* exist
*/
@RemoteMethod()
public void setProperty(PropertyLocator locator, String propertySet,
String propertyName, Object propertyValue)
throws PropertyValidationException, EntityNotFoundException {
Connection conn = null;
PreparedStatement setPropertyStatement = null;
try {
/*
* Perform any validation, such as for data types or restricted
* values
*/
if (propertyValue == null) {
throw new PropertyValidationException();
}
if (propertyName.equals(AGE_PROPERTY)
&& !(propertyValue instanceof Long)) {
throw new PropertyValidationException();
}
conn = getConnection();
// Set the column name to update
setPropertyStatement = conn
.prepareStatement(SET_PROPERTY_STATEMENT_1
+ propertyName.toUpperCase()
+ SET_PROPERTY_STATEMENT_2);
// Set the updated value
if (propertyName.equals(AGE_PROPERTY)) {
setPropertyStatement.setLong(1, (Long) propertyValue);
} else {
setPropertyStatement.setString(1, (String) propertyValue);
}
// The userName is in the PropertyLocator's pkString
setPropertyStatement.setString(2, locator.getPkString());
int affectedRowCount = setPropertyStatement.executeUpdate();
if (affectedRowCount == 0) {
throw new EntityNotFoundException(locator.getPkString()
+ " does not exist");
}
// Update the cache
PropertyMapKey propertyMapKey = new PropertyMapKeyImpl(null,
propertyName);
cachePropertyValue(locator, propertyMapKey, propertyValue);
} catch (SQLException sqle) {
throw new ConfigurableEntitySystemException(sqle);
} finally {
try {
setPropertyStatement.close();
} catch (Exception e) {
}
try {
conn.close();
} catch (Exception e) {
}
}
}
/**
* Remove all properties, and the entity record, for the user entity
* identified by the given property locator.
*
* @param locator
* the PropertyLocator identifying the entity to remove
* @exception EntityNotFoundException
* if the entity identified by the property locator does not
* exist
*/
@RemoteMethod()
public void removeEntity(PropertyLocator locator)
throws EntityNotFoundException {
Connection conn = null;
PreparedStatement removeEntityStatement = null;
try {
conn = getConnection();
// Remove the entity record
removeEntityStatement = conn
.prepareStatement(REMOVE_ENTITY_STATEMENT);
// The user name is in the PropertyLocator pkString
removeEntityStatement.setString(1, locator.getPkString());
int affectedRowCount = removeEntityStatement.executeUpdate();
if (affectedRowCount == 0) {
throw new EntityNotFoundException(locator.getPkString()
+ " does not exist");
}
// Remove it from the cache
removeItemFromCache(locator);
} catch (SQLException sqle) {
throw new ConfigurableEntitySystemException(sqle);
} finally {
try {
removeEntityStatement.close();
} catch (Exception e) {
}
try {
conn.close();
} catch (Exception e) {
}
}
}
/**
* Create a record for a new user entity, as identified by the given
* jndiHomeName (User or Group) and pkString. A custom EntityPropertyManager
* is not used as the default EntityPropertyManager for the ProfileManager,
* so you do not have to return a unique id for your user. Only the default
* EntityPropertyManager is required to return a unique number. Simply
* return -1.
*
* @param jndiHomeName
* the entity's home name
* @param pkString
* the entity's identifier string
* @return the newly created unique user entity id
* @exception ConfigurableEntityCreateException
* if there is an error
*/
@RemoteMethod()
public long createUniqueId(String jndiHomeName, String pkString)
throws ConfigurableEntityCreateException {
PreparedStatement createEntityStatement = null;
Connection conn = null;
try {
conn = getConnection();
createEntityStatement = conn
.prepareStatement(CREATE_ENTITY_STATEMENT);
// Create a row in the table for the new user
createEntityStatement.setString(1, pkString);
createEntityStatement.executeUpdate();
} catch (SQLException sqe) {
throw new ConfigurableEntityCreateException(sqe);
} finally {
try {
createEntityStatement.close();
} catch (Exception e) {
}
try {
conn.close();
} catch (Exception e) {
}
}
return -1;
}
/**
* Only the default EntityPropertyManager has to support this method. A
* custom EntityPropertyManager can simply throw
* java.lang.UnsupportedOperationException
*/
@RemoteMethod()
public long getUniqueId(String jndiHomeName, String pkString)
throws EntityNotFoundException {
throw new UnsupportedOperationException();
}
/**
* Only the default EntityPropertyManager has to support this method. A
* custom EntityPropertyManager can simply throw
* java.lang.UnsupportedOperationException
*/
@RemoteMethod()
public String[] getDynamicProperties(PropertyLocator locator,
String propertySet) throws EntityNotFoundException {
throw new UnsupportedOperationException();
}
/**
* Only the default EntityPropertyManager has to support this method. A
* custom EntityPropertyManager can simply throw
* java.lang.UnsupportedOperationException
*/
@RemoteMethod()
public String getHomeName(long anEntityId) throws EntityNotFoundException {
throw new UnsupportedOperationException();
}
/**
* Only the default EntityPropertyManager has to support this method. A
* custom EntityPropertyManager can simply throw
* java.lang.UnsupportedOperationException
*/
@RemoteMethod()
public PropertyLocator getPropertyLocator(long anEntityId)
throws EntityNotFoundException {
throw new UnsupportedOperationException();
}
/**
* Only the default EntityPropertyManager has to support this method. A
* custom EntityPropertyManager can simply throw
* java.lang.UnsupportedOperationException
*/
@RemoteMethod()
public String[] getEntityNames(String jndiName) throws RemoteException {
throw new UnsupportedOperationException();
}
/**
* Cache a property value for a user entity. The application-wide cache
* contains a EntityPropertyCache, which is the container used to hold the
* properties for the user entity. The application-wide cache contains
* object references, so there is no need to update the application-wide
* cache after changing the contents of the EntityPropertyCache container.
*
* @param locator
* the entity's property locator
* @param key
* the property's key
* @param value
* the value to cache
*/
private void cachePropertyValue(PropertyLocator locator,
PropertyMapKey key, Object value) {
if (!USE_CACHE) {
return;
}
// Get any existing EntityPropertyCache container for the locator
// (user).
EntityPropertyCache cacheItem = getItemFromCache(locator);
if (cacheItem != null) {
// Add property to the cache
cacheItem.put(key, value);
} else {
// There was no EntityPropertyCache for this locator, so create one.
cacheItem = new EntityPropertyCacheImpl();
// Add property to the cache
cacheItem.put(key, value);
// Put the new EntityPropertyCache container into the cache
addItemToCache(locator, cacheItem);
}
}
/**
* Remove a cached property value from the application-wide cache. The
* application-wide cache contains a EntityPropertyCache, which is the
* container used to hold the properties for the user entity. The
* application-wide cache contains object references, so there is no need to
* update the application-wide cache after changing the contents of the
* EntityPropertyCache container.
*
* @param locator
* the property locator of the user entity who owns the property
* @param key
* the property's key
*/
private void removeCachedPropertyValue(PropertyLocator locator,
PropertyMapKey key) {
if (!USE_CACHE) {
return;
}
// Get any existing EntityPropertyCache container for the locator
// (user).
EntityPropertyCache cacheItem = getItemFromCache(locator);
if (cacheItem != null) {
// Remove property from cache
cacheItem.remove(key);
}
}
/**
* Cache a set of properties that belong to a user entity. The
* EntityPropertyCache is the container for the properties. The
* EntityPropertyCache container is cached in the application-wide cache
* using the PropertyLocator for the user entity as the key.
*
* @param locator
* the user entity's property locator, to use as the cache key
* @param cacheItem
* the EntityPropertyCache holding that user entity's properties
*/
private void addItemToCache(PropertyLocator locator,
EntityPropertyCache cacheItem) {
if (!USE_CACHE) {
return;
}
Cache cache = CacheFactory.getCache(PROPERTY_CACHE_NAME);
if (cache != null) {
cache.put(locator, cacheItem);
}
}
/**
* Get the EntityPropertyCache holding the properties for a user entity. The
* EntityPropertyCache is the container for the values, it is not the
* application-wide cache. The EntityPropertyCache is what is cached in the
* application-wide cache. The application-wide cache is
* com.bea.p13n.cache.Cache
*
* @param locator
* the entity's property locator
* @return the EntityPropertyCache, or null if it was not found in the cache
*/
private EntityPropertyCache getItemFromCache(PropertyLocator locator) {
if (!USE_CACHE) {
return null;
}
EntityPropertyCache cacheItem = null;
Cache cache = CacheFactory.getCache(PROPERTY_CACHE_NAME);
if (cache != null) {
// Get any existing EntityPropertyCache container for the locator
// (user).
cacheItem = (EntityPropertyCache) cache.get(locator);
}
return cacheItem;
}
/**
* Remove all cached property values associated with a user entity
*
* @param locator
* the entity's property locator
*/
private void removeItemFromCache(PropertyLocator locator) {
if (!USE_CACHE) {
return;
}
Cache cache = CacheFactory.getCache(PROPERTY_CACHE_NAME);
if (cache != null) {
cache.remove(locator);
}
}
/**
* Gets a connection from the DataSource specified in the
* environment entry for the EJB.
*
* @return a java.sql.Connection
*/
protected Connection getConnection() {
try {
DataSource dataSource = getDataSource();
return dataSource.getConnection();
} catch (SQLException ex) {
throw new ConfigurableEntitySystemException(ex);
}
}
/**
* Gets the DataSource specified in the environment entry for
* the EJB.
*/
protected DataSource getDataSource() {
DataSource src = null;
try {
src = (DataSource) getEnvironmentProperty(DATA_SOURCE);
} catch (Exception ex) {
throw new ConfigurableEntitySystemException(ex);
}
return src;
}
/**
* This method returns the value of the specified EJB environment property.
*
* @throws javax.naming.NamingException -
* if a naming exception is encountered
*/
protected final Object getEnvironmentProperty(String propertyName)
throws NamingException {
Object envProperty = null;
InitialContext jndiContext = new InitialContext();
String lookupName = ((new StringBuffer("java:comp/env/"))
.append(propertyName)).toString();
envProperty = jndiContext.lookup(lookupName);
return envProperty;
}
}
6. Add XML file to EAR project’s META-INF (or configure this dynamically using the Portal Console)
Better way is to
a. in merged view copy p13n-profile-config.xml to project
b. Add following lines to it.
DizzyPropertyManager
DizzyPropertyManager
DizzyCustomer
DizzyUUP.jar#MyEntityPropertyManager
true
true
7. Here is the one trick: Edit generated remote interface under the EJB project’s apt_src folder and change the parent interface from EJBObject to EntityPropertyManager
8. Deploy
Seems to work great for me.
No problems at all, except there is one known WLP bug: remoteEntity is never called and so profiles are only deleted from the DB manually.
Have fun.
Do post your feedback or if you need to make it for your custom usecase.........
