Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » Please confirm Eclipelink logging "hardcoded" to DefaultSessionLog
Please confirm Eclipelink logging "hardcoded" to DefaultSessionLog [message #381284] Thu, 11 September 2008 22:55 Go to next message
Bill Blalock is currently offline Bill BlalockFriend
Messages: 118
Registered: July 2009
Location: Alabama
Senior Member
I've spent a couple of days trying to implement a third party logger,
log4j 1.2.14

To use a third party logger write a class to implement SessionLog. Is
this right. The docmentation is spares and I couldn't find any examples.

public class MySessionLog implements SessionLog, java.lang.Cloneable,
Serializable {

While debugging MySessionLog class I ran into places where
DefaultSessionLog and AbstractSessionLog is called by Eclipselink, not
SessionLog.

Does this mean Eclipselink is hardcoded (for now) so only
DefaultSessionLog can be used?

The problem is that I get two log entries each time a log(something) is
called.

It appears that DefaultSessionLog also sneaks in because it is referenced
directly. or indirectly through AbstractSessionLog. in other parts of
Eclipselink.

While debugging I found that the code ran through

org.eclipse.persistence.internal.jpa.EntityManagerSetupIm

// The sessionLog instance should be different from the
singletonLog because they have
// different state.
SessionLog singletonLog = null, sessionLog = null;
if (loggerClassName != null) {
SessionLog currentLog = session.getSessionLog();
if(loggerClassName.equals(LoggerType.ServerLogger)){
ServerPlatform serverPlatform =
session.getServerPlatform();
/* 1 */ singletonLog = serverPlatform.getServerLog();
/* 1 */ sessionLog = serverPlatform.getServerLog();
} else if
(!currentLog.getClass().getName().equals(loggerClassName)) {
// Logger class was specified and it's not what's already
there.
Class sessionLogClass =
findClassForProperty(loggerClassName,
PersistenceUnitProperties.LOGGING_LOGGER, loader);
try {
singletonLog =
(SessionLog)sessionLogClass.newInstance();
sessionLog = (SessionLog)sessionLogClass.newInstance();
} catch (Exception ex) {
throw
EntityManagerSetupException.failedToInstantiateLogger(logger ClassName,
PersistenceUnitProperties.LOGGING_LOGGER, ex);
}
}
} else if (serverPlatformChanged) {
ServerPlatform serverPlatform = session.getServerPlatform();
singletonLog = serverPlatform.getServerLog();
sessionLog = serverPlatform.getServerLog();
}

// Don't change default loggers if the new loggers have not been
created.
if (singletonLog != null && sessionLog != null) {
/* 2 */ AbstractSessionLog.setLog(singletonLog);
session.setSessionLog(sessionLog);
} else if (sessionNameChanged) {
// In JavaLog this will result in logger name changes,
// but won't affect DefaultSessionLog.
// Note, that the session hasn't change, only its name.
session.getSessionLog().setSession(session);
}

// Bug5389828. Update the logging settings for the singleton
logger.
initOrUpdateLogging(persistenceProperties,
AbstractSessionLog.getLog());
initOrUpdateLogging(persistenceProperties,
session.getSessionLog());



/* 1 */ My log class gets instantiated (eclipselink.logging.logger set to
my class). Okay so far.

/* 2 */ The instance of my logger get stuffed into AbstractSessionLog. I
presume that creates an instance of AbstractSessionLog.

later on this code is execute
org.eclipse.persistence.internal.sessions.AbstractSession
public SessionLog getSessionLog() {
if (sessionLog == null) {
setSessionLog(new DefaultSessionLog());
}
return sessionLog;
}


Am I going about writing my own logger wrong. Should I be implementing my
own DefaultSessionLog? Extending AbstractSessionLog?

Briefly searching the other source in Eclipselink I ran into these
references to DefaultSessionLog which seem suspicious.

see
org.eclipse.persistence.sessions.DatabaseSession.DatabaseSes sion
... return new DefaultSessionLog()
org.eclipse.persistence.tools.weaving.jpa.StaticWeaveProcess or
... return new DefaultSessionLog()
org.eclipse.persistence.internal.weaving.StaticWeaveClassTra nsformer
... ((DefaultSessionLog)session.getSessionLog()).setWriter(logWr iter);
org.eclipse.persistence.internal.sessions.factories.Sessions Factory
protected SessionLog buildSessionLog(LogConfig logConfig,
AbstractSession session) {
if (logConfig instanceof JavaLogConfig) {
return buildJavaLogConfig((JavaLogConfig)logConfig, session);
} else if (logConfig instanceof DefaultSessionLogConfig) {
return
buildDefaultSessionLogConfig((DefaultSessionLogConfig)logCon fig);
} else if (logConfig instanceof ServerLogConfig) {
return buildServerLogConfig((ServerLogConfig)logConfig,
session);
} else {
return null;
}
}

I'd appreciate any guidance.

Thanks
Bill Blalock
Re: Please confirm Eclipelink logging "hardcoded" to DefaultSessionLog [message #381385 is a reply to message #381284] Fri, 12 September 2008 19:06 Go to previous messageGo to next message
Michael OBrien is currently offline Michael OBrienFriend
Messages: 34
Registered: July 2009
Member
Bill,
Hi, I took a quick look at implementing a custom logger and the minimum
steps required on top of adding the logger to the session - is to set the
level and override log(SessionLogEntry sessionLogEntry).
I decided not to use a logging framework like apache commons or Log4J
yet so that I could isolate EclipseLink behavior.

I added the following to a Java SE JPA app and the custom logger got
picked at the end of the deploy() after predeploy().
Before this you will encounter 6 instantiations of the DefaultSessionLog
implementation of the SessionLog interface.

In eclipseLink we use the following implementation - I recommend that you
also subclass AbstractSessionLog
DefaultSessionLog extends AbstractSessionLog - which implements SessionLog.

There is no need to override the other log() functions as they all
eventually call log(SessionLogEntry).



This is the custom logger code....

public class CustomAbstractSessionLog extends AbstractSessionLog
implements SessionLog {
/* (non-Javadoc)
* @see
org.eclipse.persistence.logging.AbstractSessionLog#log(org.e clipse.persistence.logging.SessionLogEntry)
*/
@Override
public void log(SessionLogEntry sessionLogEntry) {
// TODO Auto-generated method stub
System.out.println("CUSTOM: " + sessionLogEntry.getMessage()); //
untranslated/undecoded message_id

}
}


This is the customizer to reference in persistence.xml....
public class JPAEclipseLinkSessionCustomizer implements SessionCustomizer {
public void customize(Session session) throws Exception {

// create a custom logger
SessionLog aCustomLogger = new CustomAbstractSessionLog();
aCustomLogger.setLevel(1); // finest
session.setSessionLog(aCustomLogger);
}
}

This is the propery that you want to add to persistence.xml

<property name="eclipselink.session.customizer"
value=" org.eclipse.persistence.example.unified.integration.JPAEclip seLinkSessionCustomizer "/>


Results:
----------------------------
I don't see double logs after the deploy() switchover to
CustomAbstractSessionLog()
The AbstractSession.getSessionLog() getter code you mention should only be
creating a new DefaultSessionLog if the sessionLog instance variable set
in the sessionCustomizer was not set.

Testing for secondary logs:
To test this, I disabled all breakpoints except on the DefaultSessionLog
constructor, DefaultSessionLog.log(SessionLogEntry), line 2079 and the one
that sets my custom logger

public SessionLog getSessionLog() {
if (sessionLog == null) {
-->2079 setSessionLog(new DefaultSessionLog());
}
return sessionLog;
}


- i did not see any new instantiations of DefaultSessionLog after the 6
before deploy switchover.

Maybe we need to also test outside of JPA with a native ORM example to be
able to reproduce your issue.

I will add the setup results of this discussion to a example wiki shortly
at...
http://wiki.eclipse.org/EclipseLink/Examples/JPA/CustomLogge r

thank you
/michael


Logs:
----------------------------

[EL Finest]: 2008.09.12
13:59:36.330--ServerSession(6386542)--Thread(Thread[main,5,m ain])--property=eclipselink.jdbc.url;
value=jdbc:oracle:thin:@10.156.53.19:1521:orcl
[EL Finest]: 2008.09.12
13:59:36.330--ServerSession(6386542)--Thread(Thread[main,5,m ain])--property=eclipselink.session.customizer;
value=org.eclipse.persistence.example.unified.integration.JP AEclipseLinkSessionCustomizer

>>>Logger switchover

CUSTOM: topLink_version
CUSTOM: login_successful
...
CUSTOM: INSERT IGNORE INTO STAT_CLASS (ID, JDK_VERSION, MODIFIED, INTERNAL,
LINES, TEST, CLASS_TYPE_CODE, NAME, VERSION, CLASS_TYPE, LABEL,
CLASS_PACKAGE) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
bind => [8627, null, 2008-07-04, null, 159, 0, null,
XMLPlatformException, concrete, null, 1626, 1366]
CUSTOM: execute_query
CUSTOM: execute_query
CUSTOM: execute_query
CUSTOM: INSERT IGNORE INTO STAT_CLASS (ID, JDK_VERSION, MODIFIED, INTERNAL,
LINES, TEST, CLASS_TYPE_CODE, NAME, VERSION, CLASS_TYPE, LABEL,
CLASS_PACKAGE) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
bind => [7573, null, 2008-07-04, null, 117, 0, null,
QueueableWeakCacheKey, concrete, null, 1626, 1242]
CUSTOM: execute_query
CUSTOM: execute_query
....
CUSTOM: commit_transaction
CUSTOM: end_unit_of_work_commit
CUSTOM: resume_unit_of_work
CUSTOM: release_unit_of_work
CUSTOM: client_released
CUSTOM: undeploy_begin
CUSTOM: sequencing_disconnected
CUSTOM: disconnect
CUSTOM: initialize_identitymaps
CUSTOM: logout_successful
CUSTOM: disconnect
CUSTOM: disconnect
CUSTOM: disconnect
CUSTOM: disconnect
CUSTOM: disconnect
CUSTOM: disconnect
CUSTOM: disconnect
CUSTOM: undeploy_end
Re: Please confirm Eclipelink logging "hardcoded" to DefaultSessionLog [message #381386 is a reply to message #381385] Fri, 12 September 2008 22:37 Go to previous messageGo to next message
Bill Blalock is currently offline Bill BlalockFriend
Messages: 118
Registered: July 2009
Location: Alabama
Senior Member
Michael

Thank you for the detailed reply. I appreciate your time. I'll study it
this weekend and modify MySessionLog using your suggestions.

I found the problem which caused double logging -- my bad. I didn't make
sure the log4j Logger object in MySessionLog was created as a singleton.
When the Eclipselink base code I sited in the post instantiated first the
singleton instance then the session instance of SessionLog two log4j
Logger objects were created instead of one. So each log() call in
Eclipselink wrote two log enteries (one by each Logger object).

While I was debugging the code, following the logic after creation of the
singleton and session SessionLog instances, I ran into the references to
AbstractSessionLog and DefaultSessionLog. Hence my post.

Thanks for the clarification.

I am replacing iBatis with EcliseLink in a Java project which now uses
log4j as its logging framework. I would like EclipseLink to include it's
log entries in the project's current logging framework. That is the
motivation for writing MySessionLog.

A side note, I spent two weeks learning enough about JPA and Eclipselink
(laughs, see other posts to this newsgroup) to do this. It uses four
tables in three schemas on an IBM box and one schema on a Mircrosoft 2005
SQL box. Once I had my Eclipselink replacements unit tested I was able to
substitute them for the iBatis implementations in less than a day! The
Eclipselink is much smaller and cleaner (no criticism of iBatis). So the
next task was to get my project and Eclipselink to log in the same
framework.

All that is to say you guys did a great job with Eclipselink (Oricle too
of course). Thank you all!

MySessionLog (actually Log4jSessionLog) in its current form implements
SessionLog. I ended up borrowing heavily from AbstractSessionLog and
DefaultSessionLog -- I saw where several log(param...) eventually all end
up in log( SessionLogEvent event). I wouldn't have to do that by
extending AbstractSessionLog instead of implementing SessionLog. For this
go around I borrowed the applicable code from AbstractSessionLog.

I let Eclipse new class wizard create the template for Log4JSessionLog by
implementing AbstractSessionLog. For each method stub I wrote code or
copied code from AbstractSessionLog. Then I grabbed a couple of goodies
from DefaultSessionLog.

I'll look at rewriting Log4jSessionLog as a subclass of AbstractSessionLog
as you suggested.

Would you like to look at what I have written? If you have the time I'd
appreciate cooments and suggestions.

I'll contibute this class to Eclipelink if it will be useful. When
Log4jSessionLog is finished it might be general enough to include in
Eclipselink. If not the final version could be included in the wiki as an
example if you and the other team members think it would be istructive.

-----------------------------------

I also intend to replace iBatis in an RCP project. FYI I am developing
one JPA project which will be used by both the Java project sited above (a
server application) and the RCP project (a desktop client for the server
application). Both of these are now in use, using iBatis.

So I plan to write a subclass of AbstractSessionLog that uses RCP logging
so the client and Eclipselink log enteries will be in the same place.

** Do you have any suggestions for that? **


Have a good weekend.
Bill Blalock
Re: Please confirm Eclipelink logging "hardcoded" to DefaultSessionLog [message #381388 is a reply to message #381386] Mon, 15 September 2008 15:11 Go to previous messageGo to next message
Michael OBrien is currently offline Michael OBrienFriend
Messages: 34
Registered: July 2009
Member
Bill,
I am glad to hear about your progress. Thank you for your comments.
We would be interested in anything you wish to forward for review.
You can enter any issue or enhancement request for EclipseLink by
entering your content in a bug using severity=enhancement at the following
URL.

https://bugs.eclipse.org/bugs/enter_bug.cgi?product=EclipseL ink

thank you
/michael
Re: Please confirm Eclipelink logging "hardcoded" to DefaultSessionLog [message #381395 is a reply to message #381385] Mon, 22 September 2008 18:37 Go to previous messageGo to next message
Bill Blalock is currently offline Bill BlalockFriend
Messages: 118
Registered: July 2009
Location: Alabama
Senior Member
Michael:

Thanks for the help! I've reached another problem and I'd appreciate your
help. Part of what you wrote:

> This is the customizer to reference in persistence.xml....
> public class JPAEclipseLinkSessionCustomizer implements SessionCustomizer {
> public void customize(Session session) throws Exception {

> // create a custom logger
> SessionLog aCustomLogger = new CustomAbstractSessionLog();
> aCustomLogger.setLevel(1); // finest
> session.setSessionLog(aCustomLogger);
> }
> }

My Log4j logger class works file when it is loaded with the
persistenance.xml property eclispelink.logging.logger.

The problem is that it is not used in place of DefaultSessionLog when
loaded in the SessionCustomizer as you suggest. For example:

SessionLog aCustomLogger = new Log4jSessionLog();
aCustomLogger.setLevel( SessionLog.INFO );
session.setSessionLog(aCustomLogger);

I know the code is executed but the logging is still done by
DefaultSessionLog and written to stdout.

I am designing a JPA project which will be used in a server environment
(needs log4j) and a Eclipse RCP plugin. So if the project needs to use
log4j the class name of the custom logger will be passed to the
SessionCustomizer.

I am having trouble doing this. I tried to copy the way in which the
DefaultSessionLog class is loaded but that isn't working for me. No
error, just my log4j customer logger isn't being used.

if ( loggerClass != null ) {
// create a custom logger
Class sessionLogClass;

if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
sessionLogClass = (Class)AccessController.doPrivileged(
new PrivilegedClassForName(
loggerClass, true, ClassLoader.getSystemClassLoader() ) );
} else {
sessionLogClass = PrivilegedAccessHelper.getClassForName(
loggerClass, true, ClassLoader.getSystemClassLoader() );
}
SessionLog aCustomLogger =
(SessionLog)sessionLogClass.newInstance();
aCustomLogger.setLevel(SessionLog.INFO );
session.setSessionLog(aCustomLogger);
}

I borrowed for your example. No errors but it isn't working. That isn't
supprising since the simpler version above didn't work either.

Do you see where I have gone wrong?

Thanks!
Bill Blalock

Michael OBrien wrote:

> Bill,
> Hi, I took a quick look at implementing a custom logger and the minimum
> steps required on top of adding the logger to the session - is to set the
> level and override log(SessionLogEntry sessionLogEntry).
> I decided not to use a logging framework like apache commons or Log4J
> yet so that I could isolate EclipseLink behavior.

> I added the following to a Java SE JPA app and the custom logger got
> picked at the end of the deploy() after predeploy().
> Before this you will encounter 6 instantiations of the DefaultSessionLog
> implementation of the SessionLog interface.

> In eclipseLink we use the following implementation - I recommend that you
> also subclass AbstractSessionLog
> DefaultSessionLog extends AbstractSessionLog - which implements SessionLog.

> There is no need to override the other log() functions as they all
> eventually call log(SessionLogEntry).



> This is the custom logger code....

> public class CustomAbstractSessionLog extends AbstractSessionLog
> implements SessionLog {
> /* (non-Javadoc)
> * @see
>
org.eclipse.persistence.logging.AbstractSessionLog#log(org.e clipse.persistence.logging.SessionLogEntry)
> */
> @Override
> public void log(SessionLogEntry sessionLogEntry) {
> // TODO Auto-generated method stub
> System.out.println("CUSTOM: " + sessionLogEntry.getMessage()); //
> untranslated/undecoded message_id

> }
> }


> This is the customizer to reference in persistence.xml....
> public class JPAEclipseLinkSessionCustomizer implements SessionCustomizer {
> public void customize(Session session) throws Exception {

> // create a custom logger
> SessionLog aCustomLogger = new CustomAbstractSessionLog();
> aCustomLogger.setLevel(1); // finest
> session.setSessionLog(aCustomLogger);
> }
> }

> This is the propery that you want to add to persistence.xml

> <property name="eclipselink.session.customizer"
>
value=" org.eclipse.persistence.example.unified.integration.JPAEclip seLinkSessionCustomizer "/>


> Results:
> ----------------------------
> I don't see double logs after the deploy() switchover to
> CustomAbstractSessionLog()
> The AbstractSession.getSessionLog() getter code you mention should only be
> creating a new DefaultSessionLog if the sessionLog instance variable set
> in the sessionCustomizer was not set.

> Testing for secondary logs:
> To test this, I disabled all breakpoints except on the DefaultSessionLog
> constructor, DefaultSessionLog.log(SessionLogEntry), line 2079 and the one
> that sets my custom logger

> public SessionLog getSessionLog() {
> if (sessionLog == null) {
> -->2079 setSessionLog(new DefaultSessionLog());
> }
> return sessionLog;
> }


> - i did not see any new instantiations of DefaultSessionLog after the 6
> before deploy switchover.

> Maybe we need to also test outside of JPA with a native ORM example to be
> able to reproduce your issue.

> I will add the setup results of this discussion to a example wiki shortly
> at...
> http://wiki.eclipse.org/EclipseLink/Examples/JPA/CustomLogge r

> thank you
> /michael


> Logs:
> ----------------------------

> [EL Finest]: 2008.09.12
>
13:59:36.330--ServerSession(6386542)--Thread(Thread[main,5,m ain])--property=eclipselink.jdbc.url;
> value=jdbc:oracle:thin:@10.156.53.19:1521:orcl
> [EL Finest]: 2008.09.12
>
13:59:36.330--ServerSession(6386542)--Thread(Thread[main,5,m ain])--property=eclipselink.session.customizer;
>
value=org.eclipse.persistence.example.unified.integration.JP AEclipseLinkSessionCustomizer

>>>>Logger switchover

> CUSTOM: topLink_version
> CUSTOM: login_successful
> ...
> CUSTOM: INSERT IGNORE INTO STAT_CLASS (ID, JDK_VERSION, MODIFIED, INTERNAL,
> LINES, TEST, CLASS_TYPE_CODE, NAME, VERSION, CLASS_TYPE, LABEL,
> CLASS_PACKAGE) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
> bind => [8627, null, 2008-07-04, null, 159, 0, null,
> XMLPlatformException, concrete, null, 1626, 1366]
> CUSTOM: execute_query
> CUSTOM: execute_query
> CUSTOM: execute_query
> CUSTOM: INSERT IGNORE INTO STAT_CLASS (ID, JDK_VERSION, MODIFIED, INTERNAL,
> LINES, TEST, CLASS_TYPE_CODE, NAME, VERSION, CLASS_TYPE, LABEL,
> CLASS_PACKAGE) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
> bind => [7573, null, 2008-07-04, null, 117, 0, null,
> QueueableWeakCacheKey, concrete, null, 1626, 1242]
> CUSTOM: execute_query
> CUSTOM: execute_query
> ....
> CUSTOM: commit_transaction
> CUSTOM: end_unit_of_work_commit
> CUSTOM: resume_unit_of_work
> CUSTOM: release_unit_of_work
> CUSTOM: client_released
> CUSTOM: undeploy_begin
> CUSTOM: sequencing_disconnected
> CUSTOM: disconnect
> CUSTOM: initialize_identitymaps
> CUSTOM: logout_successful
> CUSTOM: disconnect
> CUSTOM: disconnect
> CUSTOM: disconnect
> CUSTOM: disconnect
> CUSTOM: disconnect
> CUSTOM: disconnect
> CUSTOM: disconnect
> CUSTOM: undeploy_end
Re: Please confirm Eclipelink logging "hardcoded" to DefaultSessionLog [message #381396 is a reply to message #381395] Mon, 22 September 2008 18:54 Go to previous message
Bill Blalock is currently offline Bill BlalockFriend
Messages: 118
Registered: July 2009
Location: Alabama
Senior Member
Michael and all:

Opps ... I understand what is going on now. I was wrong, my log4j
customer logger is loaded both way.

I would appreciate any comments on how it is loaded when given the class
name. Is that right?

The problem is that a bunch of warnings are issued about converts that are
used. For example:

[EL Warning]: 2008.09.22 13:43:20.984--ServerSession(22634321)--Ignoring
default serialization on element [private java.lang.Boolean
domain_model.Xfrctl00.dueHoliday] within entity class [class
domain_model.Xfrctl00] since a @Convert is specified.
[EL Warning]: 2008.09.22 13:43:20.984--ServerSession(22634321)--Ignoring
default serialization on element [private java.lang.String
domain_model.Exftpclg00.operInfo] within entity class [class
domain_model.Exftpclg00] since a @Convert is specified.
[EL Warning]: 2008.09.22 13:43:21.093--ServerSession(20196260)--Ignoring
default serialization on element [private java.lang.String
domain_model.Ftplog01.clientHost] within entity class [class
domain_model.Ftplog01] since a @Convert is specified.

When the log4j class is loaded by persistence.xml these go to log4j.

When the log4j class is loaded by the SessionCustomizer these go to the
console. Other messages go to log4j.

Apparently logable activity takes place before the SessionCustomizer is
processed.

If the SessionLog class is specified in the persistence.xml file then all
logable activity is processed with that SessionLog.

If the SessionLog class is specified in the SessionCustomizer anything
logable that happens before the SessionCustomizer kicks in goes to the
basic DefaultSessionLog.

I don't consider this a bug. Loggable activity has to go someplace before
the SessionCustomizer kicks in.

Thanks
Bill Blalock
Previous Topic:How to use log4j with Eclipselink
Next Topic:DatabasePlatform file for Ingres
Goto Forum:
  


Current Time: Thu Nov 27 17:47:12 GMT 2014

Powered by FUDForum. Page generated in 0.05185 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software