Re: WebObjects and dependency injection (DI)

2009-09-22 Thread Andrus Adamchik


On Sep 22, 2009, at 11:31 AM, Andrus Adamchik wrote:

 We normally use Class.forName().newInstance() in some way or other  
to handle that. So can DI help me there? If yes, how?


Also there's a number of standard scenarios, where you can swap the  
actual service implementation behind the immutable injected interface  
proxy for a short period of time (e.g. within a request thread). A  
backend service may have request object injected in it, and when a  
service method is called within the request scope, the right request  
object is dynamically bound to the interface proxy. (Of course  
WORequest is not an interface, so it will require more indirection in  
WO).


In the same way you can bind your own request-scoped implementations  
of your custom services somewhere in the beginning of the request. And  
this transparently sets the execution context for all you other  
services and components.


Andrus
___
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list  (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: WebObjects and dependency injection (DI)

2009-09-22 Thread Andrus Adamchik


On Sep 22, 2009, at 9:07 AM, Anjo Krank wrote:

My argument being, I have a lot of code that depends on various  
"services" and their instantiation. But 90% of the time, this code  
depends on user input, program state and external stuff. It's very  
rare that I actually know at compile time what implementation I  
have. We normally use Class.forName().newInstance() in some way or  
other to handle that. So can DI help me there? If yes, how?


DI is just an environment to help you with your interface-based  
design. Nothing prevents you from writing a dynamic strategy-based  
service. At the same time DI it can simplify the public API of your  
services in many cases by removing environment-specific arguments from  
your method signatures. E.g.:


 	ERXSQLHelper sqlHelper = ERXSQLHelper.newSQLHelper(ec,  
model.name());

ERXSQLHelper sqlHelper = ERXSQLHelper.newSQLHelper(ec, dbc);
   	ERXSQLHelper sqlHelper = ERXSQLHelper.newSQLHelper(ec,  
channel);


may become

 ERXSQLHelper sqlHelper = sqlHelperService.newSQLHelper(model.name());
 ERXSQLHelper sqlHelper = sqlHelperService.newSQLHelper(dbc);
 ERXSQLHelper sqlHelper = sqlHelperService.newSQLHelper(channel);

So here you don't need to pass ec to the method as it is injected in  
sqlHelperService behind the scenes. This means that you don't need to  
carry over all needed parameters through the call chain, just to pass  
it down to some method. It creates some really nice refactoring  
opportunities, and again - it reduces coupling of the public API.


I should say I didn't get DI in theory until I tried it. Just like  
many programming optimizations (say OO vs. procedural) this is about a  
better abstraction which is not really obvious until you start using it.


Andrus

___
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list  (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: WebObjects and dependency injection (DI)

2009-09-22 Thread Andrus Adamchik


On Sep 22, 2009, at 10:50 AM, Lachlan Deck wrote:



Yeah, this is what I assumed Anjo was getting at - after some  
thought, of course (as Anjo's usually the king of succinctness :)


It seems to me that factory instantiations (as above) and/or making  
use of delegates provides all the opportunities for environment/ 
context-based switching that DI promises. i.e., both delegate style  
and DI style require the declaration of injection points and  
interfaces to implement, factories providing all the opportunities  
for custom implementations etc...   so Andrus would you like to  
elaborate on why you think DI would be particularly advantageous  
over these given that it would require hacks?


I haven't said it would be advantageous under WO. This remains to be  
seen. WO is not built for DI, so slapping it on top is going against  
the flow. That much I can see already.


Andrus

___
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list  (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: WebObjects and dependency injection (DI)

2009-09-22 Thread Lachlan Deck

On 22/09/2009, at 1:18 AM, Henrique Prange wrote:


Andrus Adamchik wrote:
I know it is not the traditional "WO way" of doing things, but from  
my experience using a dependency injection container in your app  
(Spring, Guice, etc.) is one single thing that you can do to  
dramatically improve the design quality, and produce flexible and  
maintainable code.


We have been using Guice with WO for some time in our projects. Our  
code become easier to test without requiring too much boilerplate  
code using a DI container.


Are you able to provide (if you've got time) some more concrete  
examples of what was easier?


WO does a bit of that on its own (such as session and application  
injection in components), but doesn't bundle a container that a  
developer could use for the custom "services" (unlike say Tapestry,  
that does have a DI container at its core).
Say I have a WO application and I'd like to use Spring or Guice to  
inject custom services in the WOComponents, instead of looking them  
up in WOApplication (or worse - defining them as static singletons  
somewhere). This sounds easy on the surface. I don't remember all  
the component creation internals now (it's been a while since I  
poked around the framework code), but I am pretty sure I can create  
them with my own factory that is DI container aware. On the other  
hand (also because I've been out of the loop on WO for quite some  
time), I am sure I am missing some pieces of the puzzle that would  
make such setup less practical or outright painful.


Instead of changing component creation internals, we've created an  
extension of ERXComponent that obtain the injector and inject the  
required members. It is not a perfect solution (you can't use  
constructor injection this way), but it is easy to implement.


Why would you want constructor injection for WOComponents?

This and the fact that DI capabilities don't seem to bother the  
rest of the community, I figured I'd ask the list on your opinions,  
while I am trying to wire this thing up in the background.

So anybody played with DI-on-WO in some form with any success?


We have an audit framework completely based on Guice. We have  
created extensions of other important classes to make it possible,  
like ERXGenericRecord and ERXEC and we have created a  
@WOSessionScoped scope to create/obtain objects per WOSession.


Just a question, Henrique: wouldn't it be better to use an ERXEC  
custom factory so that every ec created (even by included frameworks)  
are able to be scoped correctly in this sense?


We are planning to create an open source framework with this stuff.  
We are just polishing what we've done to use some new features of  
Guice 2.0.


Cheers,

Henrique
___
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list  (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/lachlan.deck%40gmail.com

This email sent to lachlan.d...@gmail.com


with regards,
--

Lachlan Deck



___
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list  (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: WebObjects and dependency injection (DI)

2009-09-22 Thread Lachlan Deck

On 22/09/2009, at 4:07 PM, Anjo Krank wrote:

I'm not sure you understand... the String thing is only the  
bottleneck. I have caller code like:


   	ERXSQLHelper sqlHelper = ERXSQLHelper.newSQLHelper(ec, model.name 
());

ERXSQLHelper sqlHelper = ERXSQLHelper.newSQLHelper(ec, dbc);
   	ERXSQLHelper sqlHelper = ERXSQLHelper.newSQLHelper(ec,  
channel);


Surely you don't suggest I need to create a "module" in every top- 
level caller?


My argument being, I have a lot of code that depends on various  
"services" and their instantiation. But 90% of the time, this code  
depends on user input, program state and external stuff. It's very  
rare that I actually know at compile time what implementation I  
have. We normally use Class.forName().newInstance() in some way or  
other to handle that. So can DI help me there? If yes, how?


Yeah, this is what I assumed Anjo was getting at - after some thought,  
of course (as Anjo's usually the king of succinctness :)


It seems to me that factory instantiations (as above) and/or making  
use of delegates provides all the opportunities for environment/ 
context-based switching that DI promises. i.e., both delegate style  
and DI style require the declaration of injection points and  
interfaces to implement, factories providing all the opportunities for  
custom implementations etc...   so Andrus would you like to elaborate  
on why you think DI would be particularly advantageous over these  
given that it would require hacks?


And Kieran: properties are there to make things *easier* I wouldn't  
want to avoid if's at the cost of putting every constructor in  
there... I dread the guy who has to deal with that after you...


Cheers, Anjo

Am 22.09.2009 um 00:11 schrieb Henrique Prange:


Hi Anjo,

You would not need a static method to create new ERXSQLHelper  
objects if you were using a DI container. For example, using Guice  
you could declare a helper property that must be injected.


@Inject
ERXSQLHelper helper;

If you were too lazy you could let the user define which  
implementation to use. For example, using Guice this is achieved  
with a Module with the following binding:


bind(ERXSQLHelper.class).to(OracleSQLHelper.class);

If I had to implement this using Guice, I would create an  
ERXSQLHelper provider that would return the right ERXSQLHelper  
based on the chosen database. Of course, to avoid the same code  
(nested ifs) inside the provider, I would refactor the way the  
database type is defined too.


IMHO, one advantage of this approach is I could create my own  
extension of ERXSQLHelper class and bind to all ERXSQLHelper  
declarations easily. I just need to create my own Module with the  
following code:


bind(ERXSQLHelper.class).to(MyOwnSQLHelper.class);

I could do the same thing with the current implementation, but I  
need to set a property that is not type safe and you had to write a  
lot of boilerplate code to support this.


Guice fail fast mechanism also helps to find problems earlier. If  
something is wrong with the bindings, an exception is thrown as  
soon as you create the Injector. In your example, I would get a  
NoClassDefFound in runtime, during a very important presentation,  
of course. :p


And last, but not least, you could bind a MockERXSQLHelper class  
when unit testing classes that depend upon ERXSQLHelper.


Cheers,

Henrique

Anjo Krank wrote:
U-huh. So how about a real world example and not these cooked up  
things. Take a look at the ERXSQLHelper. Depending on various  
types of input it creates a concrete subclass. Can DI change this  
to sth more "clean"?

Cheers, Anjo
public static ERXSQLHelper newSQLHelper(String  
databaseProductName) {

  synchronized (_sqlHelperMap) {
ERXSQLHelper sqlHelper = _sqlHelperMap.get(databaseProductName);
if (sqlHelper == null) {
  try {
String sqlHelperClassName = ERXProperties.stringForKey 
(databaseProductName + ".SQLHelper");

if (sqlHelperClassName == null) {
  if (databaseProductName.equalsIgnoreCase("frontbase")) {
sqlHelper = new FrontBaseSQLHelper();
  }
  else if (databaseProductName.equalsIgnoreCase("mysql")) {
sqlHelper = new MySQLSQLHelper();
  }
  else if (databaseProductName.equalsIgnoreCase("oracle")) {
sqlHelper = new OracleSQLHelper();
  }
  else if (databaseProductName.equalsIgnoreCase 
("postgresql")) {

sqlHelper = new PostgresqlSQLHelper();
  }
  else if (databaseProductName.equalsIgnoreCase 
("openbase")) {

sqlHelper = new OpenBaseSQLHelper();
  }
  else if (databaseProductName.equalsIgnoreCase("derby")) {
sqlHelper = new DerbySQLHelper();
  }
  else if (databaseProductName.equalsIgnoreCase 
("microsoft")) {

sqlHelper = new MicrosoftSQLHelper();
  }
  else {
try {
  sqlHelper = (ERXSQLHel

Re: WebObjects and dependency injection (DI)

2009-09-21 Thread Anjo Krank
I'm not sure you understand... the String thing is only the  
bottleneck. I have caller code like:


	ERXSQLHelper sqlHelper = ERXSQLHelper.newSQLHelper(ec, model.name 
());

ERXSQLHelper sqlHelper = ERXSQLHelper.newSQLHelper(ec, dbc);
	ERXSQLHelper sqlHelper = ERXSQLHelper.newSQLHelper(ec,  
channel);


Surely you don't suggest I need to create a "module" in every top- 
level caller?


My argument being, I have a lot of code that depends on various  
"services" and their instantiation. But 90% of the time, this code  
depends on user input, program state and external stuff. It's very  
rare that I actually know at compile time what implementation I have.  
We normally use Class.forName().newInstance() in some way or other to  
handle that. So can DI help me there? If yes, how?


And Kieran: properties are there to make things *easier* I wouldn't  
want to avoid if's at the cost of putting every constructor in  
there... I dread the guy who has to deal with that after you...


Cheers, Anjo



Am 22.09.2009 um 00:11 schrieb Henrique Prange:


Hi Anjo,

You would not need a static method to create new ERXSQLHelper  
objects if you were using a DI container. For example, using Guice  
you could declare a helper property that must be injected.


@Inject
ERXSQLHelper helper;

If you were too lazy you could let the user define which  
implementation to use. For example, using Guice this is achieved  
with a Module with the following binding:


bind(ERXSQLHelper.class).to(OracleSQLHelper.class);

If I had to implement this using Guice, I would create an  
ERXSQLHelper provider that would return the right ERXSQLHelper based  
on the chosen database. Of course, to avoid the same code (nested  
ifs) inside the provider, I would refactor the way the database type  
is defined too.


IMHO, one advantage of this approach is I could create my own  
extension of ERXSQLHelper class and bind to all ERXSQLHelper  
declarations easily. I just need to create my own Module with the  
following code:


bind(ERXSQLHelper.class).to(MyOwnSQLHelper.class);

I could do the same thing with the current implementation, but I  
need to set a property that is not type safe and you had to write a  
lot of boilerplate code to support this.


Guice fail fast mechanism also helps to find problems earlier. If  
something is wrong with the bindings, an exception is thrown as soon  
as you create the Injector. In your example, I would get a  
NoClassDefFound in runtime, during a very important presentation, of  
course. :p


And last, but not least, you could bind a MockERXSQLHelper class  
when unit testing classes that depend upon ERXSQLHelper.


Cheers,

Henrique

Anjo Krank wrote:
U-huh. So how about a real world example and not these cooked up  
things. Take a look at the ERXSQLHelper. Depending on various types  
of input it creates a concrete subclass. Can DI change this to sth  
more "clean"?

Cheers, Anjo
 public static ERXSQLHelper newSQLHelper(String  
databaseProductName) {

   synchronized (_sqlHelperMap) {
 ERXSQLHelper sqlHelper = _sqlHelperMap.get(databaseProductName);
 if (sqlHelper == null) {
   try {
 String sqlHelperClassName = ERXProperties.stringForKey 
(databaseProductName + ".SQLHelper");

 if (sqlHelperClassName == null) {
   if (databaseProductName.equalsIgnoreCase("frontbase")) {
 sqlHelper = new FrontBaseSQLHelper();
   }
   else if (databaseProductName.equalsIgnoreCase("mysql")) {
 sqlHelper = new MySQLSQLHelper();
   }
   else if (databaseProductName.equalsIgnoreCase("oracle")) {
 sqlHelper = new OracleSQLHelper();
   }
   else if (databaseProductName.equalsIgnoreCase 
("postgresql")) {

 sqlHelper = new PostgresqlSQLHelper();
   }
   else if (databaseProductName.equalsIgnoreCase 
("openbase")) {

 sqlHelper = new OpenBaseSQLHelper();
   }
   else if (databaseProductName.equalsIgnoreCase("derby")) {
 sqlHelper = new DerbySQLHelper();
   }
   else if (databaseProductName.equalsIgnoreCase 
("microsoft")) {

 sqlHelper = new MicrosoftSQLHelper();
   }
   else {
 try {
   sqlHelper = (ERXSQLHelper) Class.forName 
(ERXSQLHelper.class.getName() + "$" + databaseProductName +  
"SQLHelper").newInstance();

 }
 catch (ClassNotFoundException e) {
   sqlHelper = new ERXSQLHelper();
 }
   }
 }
 else {
   sqlHelper = (ERXSQLHelper) Class.forName 
(sqlHelperClassName).newInstance();

 }
 _sqlHelperMap.put(databaseProductName, sqlHelper);
   }
   catch (Exception e) {
 throw new NSForwardException(e, "Failed to create sql  
helper for the database with the product name '" +  
databaseProductName + "'.");

   }
 }
 return sqlH

Re: WebObjects and dependency injection (DI)

2009-09-21 Thread Henrique Prange

Hi Anjo,

Anjo Krank wrote:
Just so I know: does DI make anything simpler aside from unit testing? 
Is it worth the cost of un-readbility and un-debugablity?  I mean, for
foreign code i totally rely on eclipse call graphs... these are a 
nightmare with interfaces, not to mention missing constructors.




You can produce detailed object graph description using Guice Grapher 
extension (of course, you must use Guice as a DI container). I've never 
tried it, but it seems to work.


There is also a Guice plug-in for Eclipse that promises to help in this 
direction.


Cheers,

Henrique


Cheers, Anjo



Am 21.09.2009 um 21:17 schrieb Andrus Adamchik:


Hi Henrique,

Nice, thanks for sharing this info. Yeah, going through WOApplication 
and WOComponentDefinition, I realized I was too optimistic. Most 
interesting methods that would've enabled DI integration are all 
private. Quite a bit of code to rewrite to make it work. I was even 
thinking of limiting injection to just the Application class.


Great that you are willing to open source your work in this area. Even 
if you load your code in its current state to a public SVN 
(ObjectStyle.org is always an option) or git somewhere, it will be a 
rather helpful example.


Cheers,
Andrus

-
Andrus Adamchik
Apache Cayenne ORM: http://cayenne.apache.org/
Creator of Cayenne, VP Apache Software Foundation


On Sep 21, 2009, at 6:18 PM, Henrique Prange wrote:

Hi Andrus,

Andrus Adamchik wrote:
I know it is not the traditional "WO way" of doing things, but from 
my experience using a dependency injection container in your app 
(Spring, Guice, etc.) is one single thing that you can do to 
dramatically improve the design quality, and produce flexible and 
maintainable code.


We have been using Guice with WO for some time in our projects. Our 
code become easier to test without requiring too much boilerplate 
code using a DI container.


WO does a bit of that on its own (such as session and application 
injection in components), but doesn't bundle a container that a 
developer could use for the custom "services" (unlike say Tapestry, 
that does have a DI container at its core).
Say I have a WO application and I'd like to use Spring or Guice to 
inject custom services in the WOComponents, instead of looking them 
up in WOApplication (or worse - defining them as static singletons 
somewhere). This sounds easy on the surface. I don't remember all 
the component creation internals now (it's been a while since I 
poked around the framework code), but I am pretty sure I can create 
them with my own factory that is DI container aware. On the other 
hand (also because I've been out of the loop on WO for quite some 
time), I am sure I am missing some pieces of the puzzle that would 
make such setup less practical or outright painful.


Instead of changing component creation internals, we've created an 
extension of ERXComponent that obtain the injector and inject the 
required members. It is not a perfect solution (you can't use 
constructor injection this way), but it is easy to implement.


This and the fact that DI capabilities don't seem to bother the rest 
of the community, I figured I'd ask the list on your opinions, while 
I am trying to wire this thing up in the background.

So anybody played with DI-on-WO in some form with any success?


We have an audit framework completely based on Guice. We have created 
extensions of other important classes to make it possible, like 
ERXGenericRecord and ERXEC and we have created a @WOSessionScoped 
scope to create/obtain objects per WOSession.


We are planning to create an open source framework with this stuff. 
We are just polishing what we've done to use some new features of 
Guice 2.0.


Cheers,

Henrique


___
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list  (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/anjo%40krank.net

This email sent to a...@krank.net


___
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list  (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/hprange%40gmail.com

This email sent to hpra...@gmail.com

___
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list  (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: WebObjects and dependency injection (DI)

2009-09-21 Thread Henrique Prange

Hi Anjo,

You would not need a static method to create new ERXSQLHelper objects if 
you were using a DI container. For example, using Guice you could 
declare a helper property that must be injected.


@Inject
ERXSQLHelper helper;

If you were too lazy you could let the user define which implementation 
to use. For example, using Guice this is achieved with a Module with the 
following binding:


bind(ERXSQLHelper.class).to(OracleSQLHelper.class);

If I had to implement this using Guice, I would create an ERXSQLHelper 
provider that would return the right ERXSQLHelper based on the chosen 
database. Of course, to avoid the same code (nested ifs) inside the 
provider, I would refactor the way the database type is defined too.


IMHO, one advantage of this approach is I could create my own extension 
of ERXSQLHelper class and bind to all ERXSQLHelper declarations easily. 
I just need to create my own Module with the following code:


bind(ERXSQLHelper.class).to(MyOwnSQLHelper.class);

I could do the same thing with the current implementation, but I need to 
set a property that is not type safe and you had to write a lot of 
boilerplate code to support this.


Guice fail fast mechanism also helps to find problems earlier. If 
something is wrong with the bindings, an exception is thrown as soon as 
you create the Injector. In your example, I would get a NoClassDefFound 
in runtime, during a very important presentation, of course. :p


And last, but not least, you could bind a MockERXSQLHelper class when 
unit testing classes that depend upon ERXSQLHelper.


Cheers,

Henrique

Anjo Krank wrote:
U-huh. So how about a real world example and not these cooked up things. 
Take a look at the ERXSQLHelper. Depending on various types of input it 
creates a concrete subclass. Can DI change this to sth more "clean"?


Cheers, Anjo

  public static ERXSQLHelper newSQLHelper(String databaseProductName) {
synchronized (_sqlHelperMap) {
  ERXSQLHelper sqlHelper = _sqlHelperMap.get(databaseProductName);
  if (sqlHelper == null) {
try {
  String sqlHelperClassName = 
ERXProperties.stringForKey(databaseProductName + ".SQLHelper");

  if (sqlHelperClassName == null) {
if (databaseProductName.equalsIgnoreCase("frontbase")) {
  sqlHelper = new FrontBaseSQLHelper();
}
else if (databaseProductName.equalsIgnoreCase("mysql")) {
  sqlHelper = new MySQLSQLHelper();
}
else if (databaseProductName.equalsIgnoreCase("oracle")) {
  sqlHelper = new OracleSQLHelper();
}
else if (databaseProductName.equalsIgnoreCase("postgresql")) {
  sqlHelper = new PostgresqlSQLHelper();
}
else if (databaseProductName.equalsIgnoreCase("openbase")) {
  sqlHelper = new OpenBaseSQLHelper();
}
else if (databaseProductName.equalsIgnoreCase("derby")) {
  sqlHelper = new DerbySQLHelper();
}
else if (databaseProductName.equalsIgnoreCase("microsoft")) {
  sqlHelper = new MicrosoftSQLHelper();
}
else {
  try {
sqlHelper = (ERXSQLHelper) 
Class.forName(ERXSQLHelper.class.getName() + "$" + databaseProductName + 
"SQLHelper").newInstance();

  }
  catch (ClassNotFoundException e) {
sqlHelper = new ERXSQLHelper();
  }
}
  }
  else {
sqlHelper = (ERXSQLHelper) 
Class.forName(sqlHelperClassName).newInstance();

  }
  _sqlHelperMap.put(databaseProductName, sqlHelper);
}
catch (Exception e) {
  throw new NSForwardException(e, "Failed to create sql helper 
for the database with the product name '" + databaseProductName + "'.");

}
  }
  return sqlHelper;
}
  }



Am 21.09.2009 um 23:24 schrieb Andrew Lindesay:


Hi Anjo;

I guess this could be helpful in _some_ situations; I take for 
example, the Jetty server.  Jetty can have a number of "handlers" 
added to it.  Each handler does something like re-writes, feeds 
disk-based content, runs servlets etc.. etc..  The Jetty authors could 
not have envisaged all of the possible handlers that might have been 
written for Jetty, but because of the configuration style which 
follows the same line of thinking as Andrus is describing, it is 
possible to configure additional handlers.  So that's a good example 
of where this seems quite helpful and Andrus' other examples also feel 
like good examples, but I agree that it seems like over-kill for many 
situations.


cheers.

Thanks for the write-up, but yeah, this can all be achieved w/o it. I 
really don't see why I shouldn't configure my app with 
if(Configration.isStaging())... and instead use DI. At least my way I 
easily find all the occurrences and have full logic support 
if(!Configuration.isStaging()). How is D

Re: WebObjects and dependency injection (DI)

2009-09-21 Thread Kieran Kelleher
To keep stuff like this below 'clean', I define a list of properties  
and lookup the property to get the class name


er 
.extensions.sqlHelper.className.mysql=er.extensions.jdbc.MySQLSQLHelper
er.extensions.sqlHelper.className.frontbase  
=er.extensions.jdbc.FrontBaseSQLHelper


etc.

.. and create it like this

Class.forName( "er.extensions.sqlHelper.className." +  
databaseProductName ).newInstance()



YMMV, Kieran

On Sep 21, 2009, at 5:30 PM, Anjo Krank wrote:

U-huh. So how about a real world example and not these cooked up  
things. Take a look at the ERXSQLHelper. Depending on various types  
of input it creates a concrete subclass. Can DI change this to sth  
more "clean"?


Cheers, Anjo

 public static ERXSQLHelper newSQLHelper(String databaseProductName) {
   synchronized (_sqlHelperMap) {
 ERXSQLHelper sqlHelper = _sqlHelperMap.get(databaseProductName);
 if (sqlHelper == null) {
   try {
 String sqlHelperClassName =  
ERXProperties.stringForKey(databaseProductName + ".SQLHelper");

 if (sqlHelperClassName == null) {
   if (databaseProductName.equalsIgnoreCase("frontbase")) {
 sqlHelper = new FrontBaseSQLHelper();
   }
   else if (databaseProductName.equalsIgnoreCase("mysql")) {
 sqlHelper = new MySQLSQLHelper();
   }
   else if (databaseProductName.equalsIgnoreCase("oracle")) {
 sqlHelper = new OracleSQLHelper();
   }
   else if  
(databaseProductName.equalsIgnoreCase("postgresql")) {

 sqlHelper = new PostgresqlSQLHelper();
   }
   else if  
(databaseProductName.equalsIgnoreCase("openbase")) {

 sqlHelper = new OpenBaseSQLHelper();
   }
   else if (databaseProductName.equalsIgnoreCase("derby")) {
 sqlHelper = new DerbySQLHelper();
   }
   else if  
(databaseProductName.equalsIgnoreCase("microsoft")) {

 sqlHelper = new MicrosoftSQLHelper();
   }
   else {
 try {
   sqlHelper = (ERXSQLHelper)  
Class.forName(ERXSQLHelper.class.getName() + "$" +  
databaseProductName + "SQLHelper").newInstance();

 }
 catch (ClassNotFoundException e) {
   sqlHelper = new ERXSQLHelper();
 }
   }
 }
 else {
   sqlHelper = (ERXSQLHelper)  
Class.forName(sqlHelperClassName).newInstance();

 }
 _sqlHelperMap.put(databaseProductName, sqlHelper);
   }
   catch (Exception e) {
 throw new NSForwardException(e, "Failed to create sql  
helper for the database with the product name '" +  
databaseProductName + "'.");

   }
 }
 return sqlHelper;
   }
 }



Am 21.09.2009 um 23:24 schrieb Andrew Lindesay:


Hi Anjo;

I guess this could be helpful in _some_ situations; I take for  
example, the Jetty server.  Jetty can have a number of "handlers"  
added to it.  Each handler does something like re-writes, feeds  
disk-based content, runs servlets etc.. etc..  The Jetty authors  
could not have envisaged all of the possible handlers that might  
have been written for Jetty, but because of the configuration style  
which follows the same line of thinking as Andrus is describing, it  
is possible to configure additional handlers.  So that's a good  
example of where this seems quite helpful and Andrus' other  
examples also feel like good examples, but I agree that it seems  
like over-kill for many situations.


cheers.

Thanks for the write-up, but yeah, this can all be achieved w/o  
it. I really don't see why I shouldn't configure my app with  
if(Configration.isStaging())... and instead use DI. At least my  
way I easily find all the occurrences and have full logic support  
if(!Configuration.isStaging()). How is DI "cleaner" in any way when:


- I have any number of DI containers and their various syntax to  
chose from
- I can't *find* the dependencies when I really want or need them.  
Have you ever tried to debug such an app that wasn't written by  
yourself? Take a look at the Red5 Media server for some fun...


___
Andrew Lindesay
www.lindesay.co.nz



___
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list  (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/kieran_lists%40mac.com

This email sent to kieran_li...@mac.com


___
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list  (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: WebObjects and dependency injection (DI)

2009-09-21 Thread Anjo Krank
U-huh. So how about a real world example and not these cooked up  
things. Take a look at the ERXSQLHelper. Depending on various types of  
input it creates a concrete subclass. Can DI change this to sth more  
"clean"?


Cheers, Anjo

  public static ERXSQLHelper newSQLHelper(String databaseProductName) {
synchronized (_sqlHelperMap) {
  ERXSQLHelper sqlHelper = _sqlHelperMap.get(databaseProductName);
  if (sqlHelper == null) {
try {
  String sqlHelperClassName = ERXProperties.stringForKey 
(databaseProductName + ".SQLHelper");

  if (sqlHelperClassName == null) {
if (databaseProductName.equalsIgnoreCase("frontbase")) {
  sqlHelper = new FrontBaseSQLHelper();
}
else if (databaseProductName.equalsIgnoreCase("mysql")) {
  sqlHelper = new MySQLSQLHelper();
}
else if (databaseProductName.equalsIgnoreCase("oracle")) {
  sqlHelper = new OracleSQLHelper();
}
else if (databaseProductName.equalsIgnoreCase 
("postgresql")) {

  sqlHelper = new PostgresqlSQLHelper();
}
else if (databaseProductName.equalsIgnoreCase 
("openbase")) {

  sqlHelper = new OpenBaseSQLHelper();
}
else if (databaseProductName.equalsIgnoreCase("derby")) {
  sqlHelper = new DerbySQLHelper();
}
else if (databaseProductName.equalsIgnoreCase 
("microsoft")) {

  sqlHelper = new MicrosoftSQLHelper();
}
else {
  try {
sqlHelper = (ERXSQLHelper) Class.forName 
(ERXSQLHelper.class.getName() + "$" + databaseProductName +  
"SQLHelper").newInstance();

  }
  catch (ClassNotFoundException e) {
sqlHelper = new ERXSQLHelper();
  }
}
  }
  else {
sqlHelper = (ERXSQLHelper) Class.forName 
(sqlHelperClassName).newInstance();

  }
  _sqlHelperMap.put(databaseProductName, sqlHelper);
}
catch (Exception e) {
  throw new NSForwardException(e, "Failed to create sql  
helper for the database with the product name '" + databaseProductName  
+ "'.");

}
  }
  return sqlHelper;
}
  }



Am 21.09.2009 um 23:24 schrieb Andrew Lindesay:


Hi Anjo;

I guess this could be helpful in _some_ situations; I take for  
example, the Jetty server.  Jetty can have a number of "handlers"  
added to it.  Each handler does something like re-writes, feeds disk- 
based content, runs servlets etc.. etc..  The Jetty authors could  
not have envisaged all of the possible handlers that might have been  
written for Jetty, but because of the configuration style which  
follows the same line of thinking as Andrus is describing, it is  
possible to configure additional handlers.  So that's a good example  
of where this seems quite helpful and Andrus' other examples also  
feel like good examples, but I agree that it seems like over-kill  
for many situations.


cheers.

Thanks for the write-up, but yeah, this can all be achieved w/o it.  
I really don't see why I shouldn't configure my app with if 
(Configration.isStaging())... and instead use DI. At least my way I  
easily find all the occurrences and have full logic support if(! 
Configuration.isStaging()). How is DI "cleaner" in any way when:


- I have any number of DI containers and their various syntax to  
chose from
- I can't *find* the dependencies when I really want or need them.  
Have you ever tried to debug such an app that wasn't written by  
yourself? Take a look at the Red5 Media server for some fun...


___
Andrew Lindesay
www.lindesay.co.nz



___
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list  (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: WebObjects and dependency injection (DI)

2009-09-21 Thread Andrew Lindesay

Hi Anjo;

I guess this could be helpful in _some_ situations; I take for  
example, the Jetty server.  Jetty can have a number of "handlers"  
added to it.  Each handler does something like re-writes, feeds disk- 
based content, runs servlets etc.. etc..  The Jetty authors could not  
have envisaged all of the possible handlers that might have been  
written for Jetty, but because of the configuration style which  
follows the same line of thinking as Andrus is describing, it is  
possible to configure additional handlers.  So that's a good example  
of where this seems quite helpful and Andrus' other examples also feel  
like good examples, but I agree that it seems like over-kill for many  
situations.


cheers.

Thanks for the write-up, but yeah, this can all be achieved w/o it.  
I really don't see why I shouldn't configure my app with  
if(Configration.isStaging())... and instead use DI. At least my way  
I easily find all the occurrences and have full logic support if(! 
Configuration.isStaging()). How is DI "cleaner" in any way when:


- I have any number of DI containers and their various syntax to  
chose from
- I can't *find* the dependencies when I really want or need them.  
Have you ever tried to debug such an app that wasn't written by  
yourself? Take a look at the Red5 Media server for some fun...


___
Andrew Lindesay
www.lindesay.co.nz

___
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list  (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: WebObjects and dependency injection (DI)

2009-09-21 Thread Anjo Krank

Am 21.09.2009 um 22:46 schrieb Andrus Adamchik:

To be sure all of that can be achieved without DI. DI just makes it  
declarative and cleaner, and actually encourages you to follow this  
specific development pattern.



Thanks for the write-up, but yeah, this can all be achieved w/o it. I  
really don't see why I shouldn't configure my app with if 
(Configration.isStaging())... and instead use DI. At least my way I  
easily find all the occurrences and have full logic support if(! 
Configuration.isStaging()). How is DI "cleaner" in any way when:


- I have any number of DI containers and their various syntax to chose  
from
- I can't *find* the dependencies when I really want or need them.  
Have you ever tried to debug such an app that wasn't written by  
yourself? Take a look at the Red5 Media server for some fun...


Cheers, Anjo

___
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list  (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: WebObjects and dependency injection (DI)

2009-09-21 Thread Andrus Adamchik
Personally I don't even care that much about unit testing web  
applications. In data-driven apps, even with DI, it is hard to create  
good mock data for most of your services, as it may depend on a pretty  
deep object graph.


To me DI is all about clean design and decoupling of functionality  
from configuration. Implementing core application services as  
interfaces is one part of it (not really dependent on DI), but DI  
serves as a glue for those services. At the end it gives you  
flexibility to tweak things by swapping implementations of services  
without touching the components or writing endless if/else manual  
configuration code.


One real-life example is a CMS system that would generate vhost based  
URLs when in production (http://vhost.example.org) and path-based URLs  
in development environment with no DNS capability (http://localhost/vhost 
).


Another one from the CMS realm is a cache service that is implemented  
differently depending on whether the same application is in live mode  
vs. preview mode, allowing for instantaneous page refreshing in  
preview mode and best performance on a live site.


Then there's all the interceptors that you can build around interface  
method calls. I don't use it too often personally, but on a rare  
occasion when you need it, this is priceless.


To be sure all of that can be achieved without DI. DI just makes it  
declarative and cleaner, and actually encourages you to follow this  
specific development pattern.


Andrus


On Sep 21, 2009, at 11:22 PM, Anjo Krank wrote:
Just so I know: does DI make anything simpler aside from unit  
testing? Is it worth the cost of un-readbility and un-debugablity? I  
mean, for foreign code i totally rely on eclipse call graphs...  
these are a nightmare with interfaces, not to mention missing  
constructors.


Cheers, Anjo



Am 21.09.2009 um 21:17 schrieb Andrus Adamchik:


Hi Henrique,

Nice, thanks for sharing this info. Yeah, going through  
WOApplication and WOComponentDefinition, I realized I was too  
optimistic. Most interesting methods that would've enabled DI  
integration are all private. Quite a bit of code to rewrite to make  
it work. I was even thinking of limiting injection to just the  
Application class.


Great that you are willing to open source your work in this area.  
Even if you load your code in its current state to a public SVN  
(ObjectStyle.org is always an option) or git somewhere, it will be  
a rather helpful example.


Cheers,
Andrus

-
Andrus Adamchik
Apache Cayenne ORM: http://cayenne.apache.org/
Creator of Cayenne, VP Apache Software Foundation


On Sep 21, 2009, at 6:18 PM, Henrique Prange wrote:

Hi Andrus,

Andrus Adamchik wrote:
I know it is not the traditional "WO way" of doing things, but  
from my experience using a dependency injection container in your  
app (Spring, Guice, etc.) is one single thing that you can do to  
dramatically improve the design quality, and produce flexible and  
maintainable code.


We have been using Guice with WO for some time in our projects.  
Our code become easier to test without requiring too much  
boilerplate code using a DI container.


WO does a bit of that on its own (such as session and application  
injection in components), but doesn't bundle a container that a  
developer could use for the custom "services" (unlike say  
Tapestry, that does have a DI container at its core).
Say I have a WO application and I'd like to use Spring or Guice  
to inject custom services in the WOComponents, instead of looking  
them up in WOApplication (or worse - defining them as static  
singletons somewhere). This sounds easy on the surface. I don't  
remember all the component creation internals now (it's been a  
while since I poked around the framework code), but I am pretty  
sure I can create them with my own factory that is DI container  
aware. On the other hand (also because I've been out of the loop  
on WO for quite some time), I am sure I am missing some pieces of  
the puzzle that would make such setup less practical or outright  
painful.


Instead of changing component creation internals, we've created an  
extension of ERXComponent that obtain the injector and inject the  
required members. It is not a perfect solution (you can't use  
constructor injection this way), but it is easy to implement.


This and the fact that DI capabilities don't seem to bother the  
rest of the community, I figured I'd ask the list on your  
opinions, while I am trying to wire this thing up in the  
background.

So anybody played with DI-on-WO in some form with any success?


We have an audit framework completely based on Guice. We have  
created extensions of other important classes to make it possible,  
like ERXGenericRecord and ERXEC and we have created a  
@WOSessionScoped scope to create/obtain objects per WOSession.


We are planning to create an open source framework with this  
stuff. We are just po

Re: WebObjects and dependency injection (DI)

2009-09-21 Thread Anjo Krank
Just so I know: does DI make anything simpler aside from unit testing?  
Is it worth the cost of un-readbility and un-debugablity? I mean, for  
foreign code i totally rely on eclipse call graphs... these are a  
nightmare with interfaces, not to mention missing constructors.


Cheers, Anjo



Am 21.09.2009 um 21:17 schrieb Andrus Adamchik:


Hi Henrique,

Nice, thanks for sharing this info. Yeah, going through  
WOApplication and WOComponentDefinition, I realized I was too  
optimistic. Most interesting methods that would've enabled DI  
integration are all private. Quite a bit of code to rewrite to make  
it work. I was even thinking of limiting injection to just the  
Application class.


Great that you are willing to open source your work in this area.  
Even if you load your code in its current state to a public SVN (ObjectStyle.org 
 is always an option) or git somewhere, it will be a rather helpful  
example.


Cheers,
Andrus

-
Andrus Adamchik
Apache Cayenne ORM: http://cayenne.apache.org/
Creator of Cayenne, VP Apache Software Foundation


On Sep 21, 2009, at 6:18 PM, Henrique Prange wrote:

Hi Andrus,

Andrus Adamchik wrote:
I know it is not the traditional "WO way" of doing things, but  
from my experience using a dependency injection container in your  
app (Spring, Guice, etc.) is one single thing that you can do to  
dramatically improve the design quality, and produce flexible and  
maintainable code.


We have been using Guice with WO for some time in our projects. Our  
code become easier to test without requiring too much boilerplate  
code using a DI container.


WO does a bit of that on its own (such as session and application  
injection in components), but doesn't bundle a container that a  
developer could use for the custom "services" (unlike say  
Tapestry, that does have a DI container at its core).
Say I have a WO application and I'd like to use Spring or Guice to  
inject custom services in the WOComponents, instead of looking  
them up in WOApplication (or worse - defining them as static  
singletons somewhere). This sounds easy on the surface. I don't  
remember all the component creation internals now (it's been a  
while since I poked around the framework code), but I am pretty  
sure I can create them with my own factory that is DI container  
aware. On the other hand (also because I've been out of the loop  
on WO for quite some time), I am sure I am missing some pieces of  
the puzzle that would make such setup less practical or outright  
painful.


Instead of changing component creation internals, we've created an  
extension of ERXComponent that obtain the injector and inject the  
required members. It is not a perfect solution (you can't use  
constructor injection this way), but it is easy to implement.


This and the fact that DI capabilities don't seem to bother the  
rest of the community, I figured I'd ask the list on your  
opinions, while I am trying to wire this thing up in the background.

So anybody played with DI-on-WO in some form with any success?


We have an audit framework completely based on Guice. We have  
created extensions of other important classes to make it possible,  
like ERXGenericRecord and ERXEC and we have created a  
@WOSessionScoped scope to create/obtain objects per WOSession.


We are planning to create an open source framework with this stuff.  
We are just polishing what we've done to use some new features of  
Guice 2.0.


Cheers,

Henrique


___
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list  (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/anjo%40krank.net

This email sent to a...@krank.net


___
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list  (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: WebObjects and dependency injection (DI)

2009-09-21 Thread Andrus Adamchik

Hi Henrique,

Nice, thanks for sharing this info. Yeah, going through WOApplication  
and WOComponentDefinition, I realized I was too optimistic. Most  
interesting methods that would've enabled DI integration are all  
private. Quite a bit of code to rewrite to make it work. I was even  
thinking of limiting injection to just the Application class.


Great that you are willing to open source your work in this area. Even  
if you load your code in its current state to a public SVN  
(ObjectStyle.org is always an option) or git somewhere, it will be a  
rather helpful example.


Cheers,
Andrus

-
Andrus Adamchik
Apache Cayenne ORM: http://cayenne.apache.org/
Creator of Cayenne, VP Apache Software Foundation


On Sep 21, 2009, at 6:18 PM, Henrique Prange wrote:

Hi Andrus,

Andrus Adamchik wrote:
I know it is not the traditional "WO way" of doing things, but from  
my experience using a dependency injection container in your app  
(Spring, Guice, etc.) is one single thing that you can do to  
dramatically improve the design quality, and produce flexible and  
maintainable code.


We have been using Guice with WO for some time in our projects. Our  
code become easier to test without requiring too much boilerplate  
code using a DI container.


WO does a bit of that on its own (such as session and application  
injection in components), but doesn't bundle a container that a  
developer could use for the custom "services" (unlike say Tapestry,  
that does have a DI container at its core).
Say I have a WO application and I'd like to use Spring or Guice to  
inject custom services in the WOComponents, instead of looking them  
up in WOApplication (or worse - defining them as static singletons  
somewhere). This sounds easy on the surface. I don't remember all  
the component creation internals now (it's been a while since I  
poked around the framework code), but I am pretty sure I can create  
them with my own factory that is DI container aware. On the other  
hand (also because I've been out of the loop on WO for quite some  
time), I am sure I am missing some pieces of the puzzle that would  
make such setup less practical or outright painful.


Instead of changing component creation internals, we've created an  
extension of ERXComponent that obtain the injector and inject the  
required members. It is not a perfect solution (you can't use  
constructor injection this way), but it is easy to implement.


This and the fact that DI capabilities don't seem to bother the  
rest of the community, I figured I'd ask the list on your opinions,  
while I am trying to wire this thing up in the background.

So anybody played with DI-on-WO in some form with any success?


We have an audit framework completely based on Guice. We have  
created extensions of other important classes to make it possible,  
like ERXGenericRecord and ERXEC and we have created a  
@WOSessionScoped scope to create/obtain objects per WOSession.


We are planning to create an open source framework with this stuff.  
We are just polishing what we've done to use some new features of  
Guice 2.0.


Cheers,

Henrique


___
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list  (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: WebObjects and dependency injection (DI)

2009-09-21 Thread Henrique Prange

Hi Andrus,

Andrus Adamchik wrote:
I know it is not the traditional "WO way" of doing things, but from my 
experience using a dependency injection container in your app (Spring, 
Guice, etc.) is one single thing that you can do to dramatically improve 
the design quality, and produce flexible and maintainable code.




We have been using Guice with WO for some time in our projects. Our code 
become easier to test without requiring too much boilerplate code using 
a DI container.


WO does a bit of that on its own (such as session and application 
injection in components), but doesn't bundle a container that a 
developer could use for the custom "services" (unlike say Tapestry, that 
does have a DI container at its core).


Say I have a WO application and I'd like to use Spring or Guice to 
inject custom services in the WOComponents, instead of looking them up 
in WOApplication (or worse - defining them as static singletons 
somewhere). This sounds easy on the surface. I don't remember all the 
component creation internals now (it's been a while since I poked around 
the framework code), but I am pretty sure I can create them with my own 
factory that is DI container aware. On the other hand (also because I've 
been out of the loop on WO for quite some time), I am sure I am missing 
some pieces of the puzzle that would make such setup less practical or 
outright painful.




Instead of changing component creation internals, we've created an 
extension of ERXComponent that obtain the injector and inject the 
required members. It is not a perfect solution (you can't use 
constructor injection this way), but it is easy to implement.


This and the fact that DI capabilities don't seem to bother the rest of 
the community, I figured I'd ask the list on your opinions, while I am 
trying to wire this thing up in the background.


So anybody played with DI-on-WO in some form with any success?



We have an audit framework completely based on Guice. We have created 
extensions of other important classes to make it possible, like 
ERXGenericRecord and ERXEC and we have created a @WOSessionScoped scope 
to create/obtain objects per WOSession.


We are planning to create an open source framework with this stuff. We 
are just polishing what we've done to use some new features of Guice 2.0.


Cheers,

Henrique
___
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list  (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com