interface. Has the following
responsibilites
This class must appear immutable to clients, even if it does all kinds of caching
and pooling under the covers. It is crucial that the class is not only thread
safe, but also highly concurrent. Synchronization must be used extremely sparingly.
| Constructor: |
public SessionFactoryImpl(Configuration cfg,
Mapping mapping,
Settings settings,
EventListeners listeners,
SessionFactoryObserver observer) throws HibernateException {
log.info("building session factory");
this.properties = new Properties();
this.properties.putAll( cfg.getProperties() );
this.interceptor = cfg.getInterceptor();
this.settings = settings;
this.sqlFunctionRegistry = new SQLFunctionRegistry(settings.getDialect(), cfg.getSqlFunctions());
this.eventListeners = listeners;
this.observer = observer != null ? observer : new SessionFactoryObserver() {
public void sessionFactoryCreated(SessionFactory factory) {
}
public void sessionFactoryClosed(SessionFactory factory) {
}
};
this.filters = new HashMap();
this.filters.putAll( cfg.getFilterDefinitions() );
if ( log.isDebugEnabled() ) {
log.debug("Session factory constructed with filter configurations : " + filters);
}
if ( log.isDebugEnabled() ) {
log.debug(
"instantiating session factory with properties: " + properties
);
}
// Caches
settings.getRegionFactory().start( settings, properties );
//Generators:
identifierGenerators = new HashMap();
Iterator classes = cfg.getClassMappings();
while ( classes.hasNext() ) {
PersistentClass model = (PersistentClass) classes.next();
if ( !model.isInherited() ) {
IdentifierGenerator generator = model.getIdentifier().createIdentifierGenerator(
settings.getDialect(),
settings.getDefaultCatalogName(),
settings.getDefaultSchemaName(),
(RootClass) model
);
identifierGenerators.put( model.getEntityName(), generator );
}
}
///////////////////////////////////////////////////////////////////////
// Prepare persisters and link them up with their cache
// region/access-strategy
final String cacheRegionPrefix = settings.getCacheRegionPrefix() == null ? "" : settings.getCacheRegionPrefix() + ".";
entityPersisters = new HashMap();
Map entityAccessStrategies = new HashMap();
Map classMeta = new HashMap();
classes = cfg.getClassMappings();
while ( classes.hasNext() ) {
final PersistentClass model = (PersistentClass) classes.next();
model.prepareTemporaryTables( mapping, settings.getDialect() );
final String cacheRegionName = cacheRegionPrefix + model.getRootClass().getCacheRegionName();
// cache region is defined by the root-class in the hierarchy...
EntityRegionAccessStrategy accessStrategy = ( EntityRegionAccessStrategy ) entityAccessStrategies.get( cacheRegionName );
if ( accessStrategy == null && settings.isSecondLevelCacheEnabled() ) {
final AccessType accessType = AccessType.parse( model.getCacheConcurrencyStrategy() );
if ( accessType != null ) {
log.trace( "Building cache for entity data [" + model.getEntityName() + "]" );
EntityRegion entityRegion = settings.getRegionFactory().buildEntityRegion( cacheRegionName, properties, CacheDataDescriptionImpl.decode( model ) );
accessStrategy = entityRegion.buildAccessStrategy( accessType );
entityAccessStrategies.put( cacheRegionName, accessStrategy );
allCacheRegions.put( cacheRegionName, entityRegion );
}
}
EntityPersister cp = PersisterFactory.createClassPersister( model, accessStrategy, this, mapping );
entityPersisters.put( model.getEntityName(), cp );
classMeta.put( model.getEntityName(), cp.getClassMetadata() );
}
classMetadata = Collections.unmodifiableMap(classMeta);
Map tmpEntityToCollectionRoleMap = new HashMap();
collectionPersisters = new HashMap();
Iterator collections = cfg.getCollectionMappings();
while ( collections.hasNext() ) {
Collection model = (Collection) collections.next();
final String cacheRegionName = cacheRegionPrefix + model.getCacheRegionName();
final AccessType accessType = AccessType.parse( model.getCacheConcurrencyStrategy() );
CollectionRegionAccessStrategy accessStrategy = null;
if ( accessType != null && settings.isSecondLevelCacheEnabled() ) {
log.trace( "Building cache for collection data [" + model.getRole() + "]" );
CollectionRegion collectionRegion = settings.getRegionFactory().buildCollectionRegion( cacheRegionName, properties, CacheDataDescriptionImpl.decode( model ) );
accessStrategy = collectionRegion.buildAccessStrategy( accessType );
entityAccessStrategies.put( cacheRegionName, accessStrategy );
allCacheRegions.put( cacheRegionName, collectionRegion );
}
CollectionPersister persister = PersisterFactory.createCollectionPersister( cfg, model, accessStrategy, this) ;
collectionPersisters.put( model.getRole(), persister.getCollectionMetadata() );
Type indexType = persister.getIndexType();
if ( indexType != null && indexType.isAssociationType() && !indexType.isAnyType() ) {
String entityName = ( ( AssociationType ) indexType ).getAssociatedEntityName( this );
Set roles = ( Set ) tmpEntityToCollectionRoleMap.get( entityName );
if ( roles == null ) {
roles = new HashSet();
tmpEntityToCollectionRoleMap.put( entityName, roles );
}
roles.add( persister.getRole() );
}
Type elementType = persister.getElementType();
if ( elementType.isAssociationType() && !elementType.isAnyType() ) {
String entityName = ( ( AssociationType ) elementType ).getAssociatedEntityName( this );
Set roles = ( Set ) tmpEntityToCollectionRoleMap.get( entityName );
if ( roles == null ) {
roles = new HashSet();
tmpEntityToCollectionRoleMap.put( entityName, roles );
}
roles.add( persister.getRole() );
}
}
collectionMetadata = Collections.unmodifiableMap(collectionPersisters);
Iterator itr = tmpEntityToCollectionRoleMap.entrySet().iterator();
while ( itr.hasNext() ) {
final Map.Entry entry = ( Map.Entry ) itr.next();
entry.setValue( Collections.unmodifiableSet( ( Set ) entry.getValue() ) );
}
collectionRolesByEntityParticipant = Collections.unmodifiableMap( tmpEntityToCollectionRoleMap );
//Named Queries:
namedQueries = new HashMap( cfg.getNamedQueries() );
namedSqlQueries = new HashMap( cfg.getNamedSQLQueries() );
sqlResultSetMappings = new HashMap( cfg.getSqlResultSetMappings() );
imports = new HashMap( cfg.getImports() );
// after *all* persisters and named queries are registered
Iterator iter = entityPersisters.values().iterator();
while ( iter.hasNext() ) {
( (EntityPersister) iter.next() ).postInstantiate();
}
iter = collectionPersisters.values().iterator();
while ( iter.hasNext() ) {
( (CollectionPersister) iter.next() ).postInstantiate();
}
//JNDI + Serialization:
name = settings.getSessionFactoryName();
try {
uuid = (String) UUID_GENERATOR.generate(null, null);
}
catch (Exception e) {
throw new AssertionFailure("Could not generate UUID");
}
SessionFactoryObjectFactory.addInstance(uuid, name, this, properties);
log.debug("instantiated session factory");
if ( settings.isAutoCreateSchema() ) {
new SchemaExport( cfg, settings ).create( false, true );
}
if ( settings.isAutoUpdateSchema() ) {
new SchemaUpdate( cfg, settings ).execute( false, true );
}
if ( settings.isAutoValidateSchema() ) {
new SchemaValidator( cfg, settings ).validate();
}
if ( settings.isAutoDropSchema() ) {
schemaExport = new SchemaExport( cfg, settings );
}
if ( settings.getTransactionManagerLookup()!=null ) {
log.debug("obtaining JTA TransactionManager");
transactionManager = settings.getTransactionManagerLookup().getTransactionManager(properties);
}
else {
if ( settings.getTransactionFactory().isTransactionManagerRequired() ) {
throw new HibernateException("The chosen transaction strategy requires access to the JTA TransactionManager");
}
transactionManager = null;
}
currentSessionContext = buildCurrentSessionContext();
if ( settings.isQueryCacheEnabled() ) {
updateTimestampsCache = new UpdateTimestampsCache(settings, properties);
queryCache = settings.getQueryCacheFactory()
.getQueryCache(null, updateTimestampsCache, settings, properties);
queryCaches = new HashMap();
allCacheRegions.put( updateTimestampsCache.getRegion().getName(), updateTimestampsCache.getRegion() );
allCacheRegions.put( queryCache.getRegion().getName(), queryCache.getRegion() );
}
else {
updateTimestampsCache = null;
queryCache = null;
queryCaches = null;
}
//checking for named queries
if ( settings.isNamedQueryStartupCheckingEnabled() ) {
Map errors = checkNamedQueries();
if ( !errors.isEmpty() ) {
Set keys = errors.keySet();
StringBuffer failingQueries = new StringBuffer( "Errors in named queries: " );
for ( Iterator iterator = keys.iterator() ; iterator.hasNext() ; ) {
String queryName = ( String ) iterator.next();
HibernateException e = ( HibernateException ) errors.get( queryName );
failingQueries.append( queryName );
if ( iterator.hasNext() ) {
failingQueries.append( ", " );
}
log.error( "Error in named query: " + queryName, e );
}
throw new HibernateException( failingQueries.toString() );
}
}
//stats
getStatistics().setStatisticsEnabled( settings.isStatisticsEnabled() );
// EntityNotFoundDelegate
EntityNotFoundDelegate entityNotFoundDelegate = cfg.getEntityNotFoundDelegate();
if ( entityNotFoundDelegate == null ) {
entityNotFoundDelegate = new EntityNotFoundDelegate() {
public void handleEntityNotFound(String entityName, Serializable id) {
throw new ObjectNotFoundException( id, entityName );
}
};
}
this.entityNotFoundDelegate = entityNotFoundDelegate;
this.observer.sessionFactoryCreated( this );
}
|
| Method from org.hibernate.impl.SessionFactoryImpl Detail: |
public void close() throws HibernateException {
if ( isClosed ) {
log.trace( "already closed" );
return;
}
log.info("closing");
isClosed = true;
Iterator iter = entityPersisters.values().iterator();
while ( iter.hasNext() ) {
EntityPersister p = (EntityPersister) iter.next();
if ( p.hasCache() ) {
p.getCacheAccessStrategy().getRegion().destroy();
}
}
iter = collectionPersisters.values().iterator();
while ( iter.hasNext() ) {
CollectionPersister p = (CollectionPersister) iter.next();
if ( p.hasCache() ) {
p.getCacheAccessStrategy().getRegion().destroy();
}
}
if ( settings.isQueryCacheEnabled() ) {
queryCache.destroy();
iter = queryCaches.values().iterator();
while ( iter.hasNext() ) {
QueryCache cache = (QueryCache) iter.next();
cache.destroy();
}
updateTimestampsCache.destroy();
}
settings.getRegionFactory().stop();
if ( settings.isAutoDropSchema() ) {
schemaExport.drop( false, true );
}
try {
settings.getConnectionProvider().close();
}
finally {
SessionFactoryObjectFactory.removeInstance(uuid, name, properties);
}
observer.sessionFactoryClosed( this );
eventListeners.destroyListeners();
}
Closes the session factory, releasing all held resources.
- cleans up used cache regions and "stops" the cache provider.
- close the JDBC connection
- remove the JNDI binding
Note: Be aware that the sessionfactory instance still can
be a "heavy" object memory wise after close() has been called. Thus
it is important to not keep referencing the instance to let the garbage
collector release the memory. |
static SessionFactoryImpl deserialize(ObjectInputStream ois) throws ClassNotFoundException, IOException {
String uuid = ois.readUTF();
boolean isNamed = ois.readBoolean();
String name = null;
if ( isNamed ) {
name = ois.readUTF();
}
Object result = SessionFactoryObjectFactory.getInstance( uuid );
if ( result == null ) {
log.trace( "could not locate session factory by uuid [" + uuid + "] during session deserialization; trying name" );
if ( isNamed ) {
result = SessionFactoryObjectFactory.getNamedInstance( name );
}
if ( result == null ) {
throw new InvalidObjectException( "could not resolve session factory during session deserialization [uuid=" + uuid + ", name=" + name + "]" );
}
}
return ( SessionFactoryImpl ) result;
}
Custom deserialization hook used during Session deserialization. |
public void evict(Class persistentClass) throws HibernateException {
EntityPersister p = getEntityPersister( persistentClass.getName() );
if ( p.hasCache() ) {
if ( log.isDebugEnabled() ) {
log.debug( "evicting second-level cache: " + p.getEntityName() );
}
p.getCacheAccessStrategy().evictAll();
}
}
|
public void evict(Class persistentClass,
Serializable id) throws HibernateException {
EntityPersister p = getEntityPersister( persistentClass.getName() );
if ( p.hasCache() ) {
if ( log.isDebugEnabled() ) {
log.debug( "evicting second-level cache: " + MessageHelper.infoString(p, id, this) );
}
CacheKey cacheKey = new CacheKey( id, p.getIdentifierType(), p.getRootEntityName(), EntityMode.POJO, this );
p.getCacheAccessStrategy().evict( cacheKey );
}
}
|
public void evictCollection(String roleName) throws HibernateException {
CollectionPersister p = getCollectionPersister( roleName );
if ( p.hasCache() ) {
if ( log.isDebugEnabled() ) {
log.debug( "evicting second-level cache: " + p.getRole() );
}
p.getCacheAccessStrategy().evictAll();
}
}
|
public void evictCollection(String roleName,
Serializable id) throws HibernateException {
CollectionPersister p = getCollectionPersister( roleName );
if ( p.hasCache() ) {
if ( log.isDebugEnabled() ) {
log.debug( "evicting second-level cache: " + MessageHelper.collectionInfoString(p, id, this) );
}
CacheKey cacheKey = new CacheKey( id, p.getKeyType(), p.getRole(), EntityMode.POJO, this );
p.getCacheAccessStrategy().evict( cacheKey );
}
}
|
public void evictEntity(String entityName) throws HibernateException {
EntityPersister p = getEntityPersister( entityName );
if ( p.hasCache() ) {
if ( log.isDebugEnabled() ) {
log.debug( "evicting second-level cache: " + p.getEntityName() );
}
p.getCacheAccessStrategy().evictAll();
}
}
|
public void evictEntity(String entityName,
Serializable id) throws HibernateException {
EntityPersister p = getEntityPersister( entityName );
if ( p.hasCache() ) {
if ( log.isDebugEnabled() ) {
log.debug( "evicting second-level cache: " + MessageHelper.infoString(p, id, this) );
}
CacheKey cacheKey = new CacheKey( id, p.getIdentifierType(), p.getRootEntityName(), EntityMode.POJO, this );
p.getCacheAccessStrategy().evict( cacheKey );
}
}
|
public void evictQueries() throws HibernateException {
if ( settings.isQueryCacheEnabled() ) {
queryCache.clear();
}
}
|
public void evictQueries(String cacheRegion) throws HibernateException {
if (cacheRegion==null) {
throw new NullPointerException("use the zero-argument form to evict the default query cache");
}
else {
synchronized (allCacheRegions) {
if ( settings.isQueryCacheEnabled() ) {
QueryCache currentQueryCache = (QueryCache) queryCaches.get(cacheRegion);
if ( currentQueryCache != null ) {
currentQueryCache.clear();
}
}
}
}
}
|
public Map getAllClassMetadata() throws HibernateException {
return classMetadata;
}
|
public Map getAllCollectionMetadata() throws HibernateException {
return collectionMetadata;
}
|
public Map getAllSecondLevelCacheRegions() {
synchronized ( allCacheRegions ) {
return new HashMap( allCacheRegions );
}
}
|
public BatcherFactory getBatcherFactory() {
return settings.getBatcherFactory();
}
|
public ClassMetadata getClassMetadata(Class persistentClass) throws HibernateException {
return getClassMetadata( persistentClass.getName() );
}
|
public ClassMetadata getClassMetadata(String entityName) throws HibernateException {
return (ClassMetadata) classMetadata.get(entityName);
}
|
public CollectionMetadata getCollectionMetadata(String roleName) throws HibernateException {
return (CollectionMetadata) collectionMetadata.get(roleName);
}
|
public CollectionPersister getCollectionPersister(String role) throws MappingException {
CollectionPersister result = (CollectionPersister) collectionPersisters.get(role);
if (result==null) {
throw new MappingException( "Unknown collection role: " + role );
}
return result;
}
|
public Set getCollectionRolesByEntityParticipant(String entityName) {
return ( Set ) collectionRolesByEntityParticipant.get( entityName );
}
|
public ConnectionProvider getConnectionProvider() {
return settings.getConnectionProvider();
}
|
public Session getCurrentSession() throws HibernateException {
if ( currentSessionContext == null ) {
throw new HibernateException( "No CurrentSessionContext configured!" );
}
return currentSessionContext.currentSession();
}
|
public Set getDefinedFilterNames() {
return filters.keySet();
}
|
public Dialect getDialect() {
return settings.getDialect();
}
|
public EntityNotFoundDelegate getEntityNotFoundDelegate() {
return entityNotFoundDelegate;
}
|
public EntityPersister getEntityPersister(String entityName) throws MappingException {
EntityPersister result = (EntityPersister) entityPersisters.get(entityName);
if (result==null) {
throw new MappingException( "Unknown entity: " + entityName );
}
return result;
}
|
public EventListeners getEventListeners() {
return eventListeners;
}
|
public FilterDefinition getFilterDefinition(String filterName) throws HibernateException {
FilterDefinition def = ( FilterDefinition ) filters.get( filterName );
if ( def == null ) {
throw new HibernateException( "No such filter configured [" + filterName + "]" );
}
return def;
}
|
public IdentifierGenerator getIdentifierGenerator(String rootEntityName) {
return (IdentifierGenerator) identifierGenerators.get(rootEntityName);
}
|
public String getIdentifierPropertyName(String className) throws MappingException {
return getEntityPersister(className).getIdentifierPropertyName();
}
|
public Type getIdentifierType(String className) throws MappingException {
return getEntityPersister(className).getIdentifierType();
}
|
public String[] getImplementors(String className) throws MappingException {
final Class clazz;
try {
clazz = ReflectHelper.classForName(className);
}
catch (ClassNotFoundException cnfe) {
return new String[] { className }; //for a dynamic-class
}
ArrayList results = new ArrayList();
Iterator iter = entityPersisters.values().iterator();
while ( iter.hasNext() ) {
//test this entity to see if we must query it
EntityPersister testPersister = (EntityPersister) iter.next();
if ( testPersister instanceof Queryable ) {
Queryable testQueryable = (Queryable) testPersister;
String testClassName = testQueryable.getEntityName();
boolean isMappedClass = className.equals(testClassName);
if ( testQueryable.isExplicitPolymorphism() ) {
if ( isMappedClass ) {
return new String[] {className}; //NOTE EARLY EXIT
}
}
else {
if (isMappedClass) {
results.add(testClassName);
}
else {
final Class mappedClass = testQueryable.getMappedClass( EntityMode.POJO );
if ( mappedClass!=null && clazz.isAssignableFrom( mappedClass ) ) {
final boolean assignableSuperclass;
if ( testQueryable.isInherited() ) {
Class mappedSuperclass = getEntityPersister( testQueryable.getMappedSuperclass() ).getMappedClass( EntityMode.POJO);
assignableSuperclass = clazz.isAssignableFrom(mappedSuperclass);
}
else {
assignableSuperclass = false;
}
if ( !assignableSuperclass ) {
results.add( testClassName );
}
}
}
}
}
}
return (String[]) results.toArray( new String[ results.size() ] );
}
Return the names of all persistent (mapped) classes that extend or implement the
given class or interface, accounting for implicit/explicit polymorphism settings
and excluding mapped subclasses/joined-subclasses of other classes in the result. |
public String getImportedClassName(String className) {
String result = (String) imports.get(className);
if (result==null) {
try {
ReflectHelper.classForName(className);
return className;
}
catch (ClassNotFoundException cnfe) {
return null;
}
}
else {
return result;
}
}
|
public Interceptor getInterceptor() {
return interceptor;
}
|
public NamedQueryDefinition getNamedQuery(String queryName) {
return (NamedQueryDefinition) namedQueries.get(queryName);
}
|
public NamedSQLQueryDefinition getNamedSQLQuery(String queryName) {
return (NamedSQLQueryDefinition) namedSqlQueries.get(queryName);
}
|
public QueryCache getQueryCache() {
return queryCache;
}
|
public QueryCache getQueryCache(String regionName) throws HibernateException {
if ( regionName == null ) {
return getQueryCache();
}
if ( !settings.isQueryCacheEnabled() ) {
return null;
}
synchronized ( allCacheRegions ) {
QueryCache currentQueryCache = ( QueryCache ) queryCaches.get( regionName );
if ( currentQueryCache == null ) {
currentQueryCache = settings.getQueryCacheFactory().getQueryCache( regionName, updateTimestampsCache, settings, properties );
queryCaches.put( regionName, currentQueryCache );
allCacheRegions.put( currentQueryCache.getRegion().getName(), currentQueryCache.getRegion() );
}
return currentQueryCache;
}
}
|
public QueryPlanCache getQueryPlanCache() {
return queryPlanCache;
}
|
public Reference getReference() throws NamingException {
log.debug("Returning a Reference to the SessionFactory");
return new Reference(
SessionFactoryImpl.class.getName(),
new StringRefAddr("uuid", uuid),
SessionFactoryObjectFactory.class.getName(),
null
);
}
|
public Type getReferencedPropertyType(String className,
String propertyName) throws MappingException {
return getEntityPersister(className).getPropertyType(propertyName);
}
|
public ResultSetMappingDefinition getResultSetMapping(String resultSetName) {
return (ResultSetMappingDefinition) sqlResultSetMappings.get(resultSetName);
}
|
public String[] getReturnAliases(String queryString) throws HibernateException {
return queryPlanCache.getHQLQueryPlan( queryString, false, CollectionHelper.EMPTY_MAP ).getReturnMetadata().getReturnAliases();
}
|
public Type[] getReturnTypes(String queryString) throws HibernateException {
return queryPlanCache.getHQLQueryPlan( queryString, false, CollectionHelper.EMPTY_MAP ).getReturnMetadata().getReturnTypes();
}
|
public SQLExceptionConverter getSQLExceptionConverter() {
return settings.getSQLExceptionConverter();
}
|
public Region getSecondLevelCacheRegion(String regionName) {
synchronized ( allCacheRegions ) {
return ( Region ) allCacheRegions.get( regionName );
}
}
|
public Settings getSettings() {
return settings;
}
|
public SQLFunctionRegistry getSqlFunctionRegistry() {
return sqlFunctionRegistry;
}
|
public Statistics getStatistics() {
return statistics;
}
|
public StatisticsImplementor getStatisticsImplementor() {
return statistics;
}
|
public TransactionFactory getTransactionFactory() {
return settings.getTransactionFactory();
}
|
public TransactionManager getTransactionManager() {
return transactionManager;
}
|
public UpdateTimestampsCache getUpdateTimestampsCache() {
return updateTimestampsCache;
}
|
public boolean isClosed() {
return isClosed;
}
|
public Session openSession() throws HibernateException {
return openSession(interceptor);
}
|
public Session openSession(Interceptor sessionLocalInterceptor) throws HibernateException {
// note that this timestamp is not correct if the connection provider
// returns an older JDBC connection that was associated with a
// transaction that was already begun before openSession() was called
// (don't know any possible solution to this!)
long timestamp = settings.getRegionFactory().nextTimestamp();
return openSession( null, true, timestamp, sessionLocalInterceptor );
}
|
public Session openSession(Connection connection) {
return openSession(connection, interceptor); //prevents this session from adding things to cache
}
|
public Session openSession(Connection connection,
Interceptor sessionLocalInterceptor) {
return openSession(connection, false, Long.MIN_VALUE, sessionLocalInterceptor);
}
|
public Session openSession(Connection connection,
boolean flushBeforeCompletionEnabled,
boolean autoCloseSessionEnabled,
ConnectionReleaseMode connectionReleaseMode) throws HibernateException {
return new SessionImpl(
connection,
this,
true,
settings.getRegionFactory().nextTimestamp(),
interceptor,
settings.getDefaultEntityMode(),
flushBeforeCompletionEnabled,
autoCloseSessionEnabled,
connectionReleaseMode
);
}
|
public StatelessSession openStatelessSession() {
return new StatelessSessionImpl( null, this );
}
|
public StatelessSession openStatelessSession(Connection connection) {
return new StatelessSessionImpl( connection, this );
}
|
public Session openTemporarySession() throws HibernateException {
return new SessionImpl(
null,
this,
true,
settings.getRegionFactory().nextTimestamp(),
interceptor,
settings.getDefaultEntityMode(),
false,
false,
ConnectionReleaseMode.AFTER_STATEMENT
);
}
|
void serialize(ObjectOutputStream oos) throws IOException {
oos.writeUTF( uuid );
oos.writeBoolean( name != null );
if ( name != null ) {
oos.writeUTF( name );
}
}
Custom serialization hook used during Session serialization. |