Hi,
What follows is a summary of the refactoring that has been
done in the Turbine sources.
----------------------------------------------------------
S E R V I C E S
----------------------------------------------------------
(1)
All services now use properties in the fully qualified
form:
services.XYZService.<property> = value
The following services have been updated to
use fully qualified properties:
GlobalCacheService
NamingService
SchedulerService
XmlRpcService
XsltService
(2)
The explicit references to Velocity Configuration class
have been removed in all services except for the
PullService. The PullService can be changed later,
the Configuration class is too handy for placing tools
in the context.
The Configuration class is still used in the base
classes of the services framework and they will
remain there until a Configuration interface is
created. The ExtendedProperties class in the commons
is the new home for the original Velocity Configuration
class, but I didn't just want to replace one concrete
implementation with another. Some work needs to be
done but I think that a Configuration interface can
be made and a set of concrete implementations can
be made that implement the Configuration interface.
Once this is done than we can use the Configuration
interface in the base classes of the service framework.
(3)
All services now get their configuration from the service
broker (or service manager as I prefer to call it) via
an accessor:
String path = getConfiguration().getString("path");
What is happening is the BaseService gets the configuration
for a service from the ServiceBroker using the SERVICE_NAME
field present in the service interface. All the services
now use this method.
(4)
There is now only a single init() method in all the services.
All init(Object o) methods have been removed and are
no longer necessary. A service is either lazily initialized,
or if the service's 'earlyInit' property is set to true
then it is started when the ServiceBroker is initialized.
(5)
All the Initable code has been removed. There are
now the following set of classes:
BaseService.java
BaseServiceBroker.java
InitializationException.java
InstantiationException.java
Service.java
ServiceBroker.java
TurbineServices.java
And it would be entirely possible to remove the
TurbineServices class as it is only there for backward
compatibility. We may very likely want to be have more
than one instance for a service, especially for subapps.
We can be part of the 2.2 discussion.
(6)
I have tried to separate the services from Turbine
proper. There are almost no references to any Turbine
specifics in any of services except those that will
never be decoupled from Turbine: like the AssemblerBroker
and the RunData service. Running Turbine in stand-alone
mode should be a lot easier, and in fact the services
are pretty much there in terms of being a separate
project. This is how the services framework is now
initialized from within the Turbine.java class:
// Get the instance of the service manager
TurbineServices serviceManager =
(TurbineServices) TurbineServices.getInstance();
// Set the service managers application root. In our
// case it is the webapp context.
serviceManager.setApplicationRoot(getApplicationRoot());
// This should eventually be a Configuration
// interface so that service and app configuration
// can be stored anywhere.
configuration = new Configuration(
getApplicationRoot() + DEFAULT_TURBINE_RESOURCES);
serviceManager.setConfiguration(configuration);
// We are using the 'default' category for logging
// when a category isn't specified. The 'default'
// category must be setup in the TRP.
serviceManager.setCategory(Category.getInstance("default"));
// The TurbineResourceService needs to access the
// whole configuration file because it really has
// no configuration of its own.
serviceManager.setServiceObject("configuration", configuration);
// Initialize the service manager. Services
// that have its 'earlyInit' property set to
// a value of 'true' will be started when
// the service manager is initialized.
serviceManager.init();
(7)
There are now a set of properties for placing objects
in the control of the ServiceBroker that can be
made available to Services:
setServiceObject(String key, Object value)
getServiceObject(String key)
I thought I would need these at first for the services
that originally needed RunData and Servlet{Config|Context}
objects but it turns out that I didn't. I left the properties
in there so that the parent application can place objects
in storage if they are required in any Services.
(8)
For services logging you just hand the ServiceBroker
a log4j Category. A Category is another name for
a logger. So with log4j it's really easy to have to
services log to the same file as the rest of the turbine
stuff, or you could easily have the services log to
a separate file.
---
There are still some gunk left in the ServiceBroker
left over from getting rid of Initable code, but I
just want to get the code in the repository.
I think these changes have made the code easier to
read and made the services more consistent. I think
we can now tackle things like:
-> fully pluggable services and packaging them
in jars
-> implementing restart() so that services can
be reconfigured and restarted on the fly without the
need to shut down Turbine
-> making the services fully self describing in terms
of the properties they support and how they
are to be configured. for app deployment it would
be nice if when a Turbine app was started for the
first time a web console could be presented to user
where the services defaults could be configured/saved
and have the app go on its way. a lot of interested
things could be done here.
----------------------------------------------------------
L O G G I N G
----------------------------------------------------------
The LoggingService as it was in 2.1 is completely gone
and has been entirely replaced by log4j. Log4j is
incredibly powerful and I think we only have things to
gain by using it.
As it stands I did not implement the logging in the
recommended fashion but placed everything within our
Log.java class. The same logging methods can be used,
but we should definitely discuss how best to use
log4j. I think Ceki will be glad to help us as well.
I will add back configuration for the SMTP Categories
and Appenders in a couple of days. You can basically
do whatever you want because we are just using standard
log4j properties embedded in our TRP file. If you want
use the SMTPAppender in log4j it's just a matter of
adding a few lines of configuration. We can fully take
advantage of all the Appenders that are present in log4j
via setting properties, no code to change.
I will put some more examples in the TRP file. Right now
I just have a the standard turbine.log and an sql.log that
can be flipped on/off by setting the priority. So if you
want to see all the SQL generated by the Peers then you
just have to change one line and all the SQL will be
logged for you.
Log4j has some nifty hierachical behavior that we
probably want to investigate further. There is also
an example of an app server logging system with
events in the log4j repository we might want to look at.
I just wanted to get us using log4j as it kicks ass!
An entire, rather complicated service has been removed
and all the logging has been completely off loaded to
log4j. I see only a benefit.
----------------------------------------------------------
P R O P E R T I E S C H A N G E S
----------------------------------------------------------
As noted above, many services had there properties
fully qualified and there is the addition of the 'earlyInit'
property to have a service startup when the ServiceBroker
is initialized.
The logging configuration is also different. It looks very
similiar to what we had, but we are now using standard
log4j properties. So the docs on the log4j website will
tell you everything you need to know. I'm certainly no
log4j expert yet, so feel free to jump in.
These property changes are not backward compatible,
but I've started making a TurbineAdaptor class that I
hope to use to transparently transform a 2.1 TRP file
so that 2.1 apps will run with change under 2.2. I don't
know how well this will work but I'm going to give it
a try. If it works than the changes made so far will
be backward compatible.
----------------------------------------------------------
B A C K W A R D C O M P A T I B I L I T Y
----------------------------------------------------------
I have tried to stay 100% backward compatible in the code,
but I am expecting GUMP and other Turbine developers to
help me out.
If you are depending on CVS HEAD than _please_ be patient.
I'll fix/adaptor anything to try and make things backward
compatible but I only have the TDK to test with and that's
not comprehensive yet.
I am slowly adding some tests, but unfortunately I've run
out of time for this refactoring session.
----------------------------------------------------------
T U R B I N E T H E F A C A D E
----------------------------------------------------------
There is a chunk of code at the bottom of Turbine.java
that now provides some standard information to
the application.
Previously the ServletService was used to get information
about the servlet (The ServletService is still there :-))
but it can now be accessed directly from the Turbine.java
class.
My idea is that we can build up a contract for our
users by using Turbine.java itself as a facade.
What I added was necessary to allow processes/classes
in a Turbine app that have no access to a RunData
object to glean info about the service. The example
I always use is that of a scheduled job that does
some processing and stores thing within the webapp
space.
This code can be moved somewhere else, but I'm interested
in pursing an API that can be based around the Turbine.java
class so we can try to close down the gates a bit. I am
constantly surprised at things that are overriden that
shouldn't be. This would be something similiar to the
Velocity helper class. Basically a contract for our
users: a single point of access. Maybe this could be
possible with some more refactoring, a unified template
services ...
Ok, I'm going to start checking in the code tomorrow
morning because I'm baked right now. So can people
lay off committing until later on tomorrow as I have
to do some merging before I commit. Everything should
be in by tomorrow afternoon. I'll be glad when we can
start talking about 2.2! :-)
--
jvz.
http://tambora.zenplex.org
http://jakarta.apache.org/turbine
http://jakarta.apache.org/velocity
http://jakarta.apache.org/alexandria
http://jakarta.apache.org/commons
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]