figleaf-developer Mailing List for Figleaf (Page 3)
Status: Alpha
Brought to you by:
steckman
You can subscribe to this list here.
| 2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(78) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2006 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: Greg S. <ste...@on...> - 2004-07-04 23:57:23
|
sam...@ma... wrote:
>Firstly, is this better off being named something like PersistenceLayer?
>
>
>
Maybe. But because I had the "Informative introspect(Object obj);"
method in there that brought it out of being purely for persistence.
Also I figured there's probably going to be non-persistence stuff we'll
need to put somewhere (logins, security?).
>Secondly, there seems to be some overlapping methods, for example (this from my
>TransientObjectManager):
>
>public Informative newInstance(Class clazz) {
> return informativeFactory.createInformative(clazz.newInstance());
>}
>
>public Informative introspect(Object obj) {
> return factory.createInformative(obj);
>}
>
>Are both needed? I'm keen not to put in a requirement for methods to be
>implemented that we might not even end up using.
>
>
The introspect method was because I thought about the case if a POJO
creates an object (using new) and returns it from a method call. Then
the UI will need to get the ObjectManager to proxy it and turn it into
an Informative so it can be displayed. Some thought still needs to be
given to when such an object should be persisted: as soon as its called,
force the user to press a save button, or never...? Then there's the
issue of what if that happens in a transaction. I'm not sure it's
practical to expect all objects to know nothing about ObjectManager and
just use new. If we require them to always use the ObjectManager when
creating a new instance, then the introspect method probably isn't needed.
>As for the method:
>
>Informative getObject(Class clazz, Serializable id);
>
>Do we need this? Surely this should be handled by whatever query mechanism we use.
>
>sam
>
>
>
>
It'll probably be needed by lazy initializing proxies and collections.
They will only know the id and which class they represent. When they
need to load their data they can call this method and get a fully
populated object back. Perhaps it doesn't belong in the ObjectManager
"layer" but rather in a persistence and proxy layer.
Greg
|
|
From: Greg S. <ste...@on...> - 2004-07-04 23:41:06
|
sam...@ma... wrote:
>Right, the InfromativeFactoryImpl now creates proxies as requested.
>
>
We've got an Introspector, InformativeFactory, and ObjectIntrospector
interfaces. I think that's at least 1 too many. ObjectIntrospector has a
method "ClassDescriptor createInformative(Object o)" that doesn't seem
to be right. Shouldn't it return an Informative?
Is it necessary for the ObjectIntrospector interface to have methods
getDescription, getDisplayName, getProperties and getProperty? Those are
all things that the ClassDescriptor interface provides. I think not, so
it then is essentially the same as Introspector.
>By way of a proof of concept, I've written a new ConfigurableBootstrapper based
>on your original code. The only difference being that it now hands-off the
>determination of which beans to use to a new ApplicationConfiguration class
>(more specifically a SpringApplicationCnfiguration). The only other difference
>is that rather than having the user specify which bean is runnable, I've assumed
>a bean called Runnable - my aim here is for things to be simple. I also added a
>TransientObjectManager which will hold objects in memory, although at present it
>doesn't do anything. The SimpleApplicationContext I use looks like this:
>
><bean id="Introspector" class="net.sourceforge.figleaf.impl.IntrospectorImpl" />
>
><bean id="ObjectManager"
>class="net.sourceforge.figleaf.impl.TransientObjectManager" />
>
><bean id="Runnable"
>class="net.sourceforge.figleaf.viewer.swing.ConfigurableSwingViewer">
> <constructor-arg>
> <ref bean="ObjectManager"/>
> </constructor-arg>
>
> <constructor-arg>
> <!-- Insert classes to register here -->
> <list>
> <value>net.sourceforge.figleaf.example.imageviewer.ImageAlbum</value>
> </list>
> </constructor-arg>
></bean>
>
>The ConfigurableBootstrapper like this:
>
>String springConfigFile = line.getOptionValue("config");
>SpringApplicationConfiguration config = new
> SpringApplicationConfiguration(springConfigFile);
>getInstance().setObjectManager(config.getObjectManager());
>
>//load the worker bean
>config.getRunnable().run();
>
>
>
I guess your main objective is to get ConfigurableBootstrapper to the
point to where it can use something other than
SpringApplicationConfiguration?
>Next, I've created a slightly different SwingViewer - my version takes all
>dependencies via constructors (which I think is neater than using setters to
>define dependencies). I've also defined internally a default view map as I think
>it's OK for us to assume default views (e.g. text entry fields) and then allow
>the developer to override it. I've also changed it so the list of registered
>classes to be passed in. All of this is by way of a test to see how simple we
>can make application setup - I'd appreciate your comments. My
>ConfigurableSwingViewer isn't as functional as yours - I originally based the
>code on yours but then realised I didn't need to reinvent the wheel, just show
>how it could be invoked.
>
Setters somehow seemed more flexible when using dependency injection,
perhaps not.
Do you have in mind how to allow the developer to override the default
view types and to provide additional view types?
Now to the classes. We have to think about this carefully. Currently a
class is represented by an InformativeDescriptor instance. It includes
information about the class (it's class name, a display name, and a
description) as well as methods that can be used to do things with that
class, such as get a new instance of it. Of course that can be done
other ways as long as you have the class name. But I wanted to
eventually be able to associate security information with the class,
such as restricting which users could create a new instance of the class
represented by a given instance of InformativeDescriptor, who can delete
an instance, etc. Additionally I wanted to be able create "context
groups" that are collections of InformativeDescriptors. So for instance
if there are classes A, B, C, and D, I can assign A and B to one context
group and C and D to a second context group. Then I can assign one user
so that on startup he sees the classes in the first context group but
not the second, and vice-versa for a second user. A user could be
allowed to see multiple context groups, for example an administrator or
other super user would have access to all context groups.
I believe this kind of complex security and relational model of classes
is only possible if there is a first-class object representing the
class. My approach was to need only 1 class seeded in the database, and
that was an InformativeDescriptor that describes itself. With that you
can create objects for all other classes needed and setup their
security, assign them to context groups, etc.
I think the best approach is to write a "system initializer" program
that would take some config file or even user input and setup the system
the first time. This would include classes for which to create default
InformativeDescptors, a super-user account, etc. Long term I think this
is right way to do it because user passwords should be stored in the
database using a 1-way hash or some other scrambling method, not in
clear text, which means we need to write a program to get the first user
in the system so they can log in and create all the others.
Greg
|
|
From: <sam...@ma...> - 2004-07-04 18:34:31
|
Firstly, is this better off being named something like PersistenceLayer?
Secondly, there seems to be some overlapping methods, for example (this from my
TransientObjectManager):
public Informative newInstance(Class clazz) {
return informativeFactory.createInformative(clazz.newInstance());
}
public Informative introspect(Object obj) {
return factory.createInformative(obj);
}
Are both needed? I'm keen not to put in a requirement for methods to be
implemented that we might not even end up using.
As for the method:
Informative getObject(Class clazz, Serializable id);
Do we need this? Surely this should be handled by whatever query mechanism we use.
sam
|
|
From: <sam...@ma...> - 2004-07-04 17:42:48
|
Right, the InfromativeFactoryImpl now creates proxies as requested.
By way of a proof of concept, I've written a new ConfigurableBootstrapper based
on your original code. The only difference being that it now hands-off the
determination of which beans to use to a new ApplicationConfiguration class
(more specifically a SpringApplicationCnfiguration). The only other difference
is that rather than having the user specify which bean is runnable, I've assumed
a bean called Runnable - my aim here is for things to be simple. I also added a
TransientObjectManager which will hold objects in memory, although at present it
doesn't do anything. The SimpleApplicationContext I use looks like this:
<bean id="Introspector" class="net.sourceforge.figleaf.impl.IntrospectorImpl" />
<bean id="ObjectManager"
class="net.sourceforge.figleaf.impl.TransientObjectManager" />
<bean id="Runnable"
class="net.sourceforge.figleaf.viewer.swing.ConfigurableSwingViewer">
<constructor-arg>
<ref bean="ObjectManager"/>
</constructor-arg>
<constructor-arg>
<!-- Insert classes to register here -->
<list>
<value>net.sourceforge.figleaf.example.imageviewer.ImageAlbum</value>
</list>
</constructor-arg>
</bean>
The ConfigurableBootstrapper like this:
String springConfigFile = line.getOptionValue("config");
SpringApplicationConfiguration config = new
SpringApplicationConfiguration(springConfigFile);
getInstance().setObjectManager(config.getObjectManager());
//load the worker bean
config.getRunnable().run();
Next, I've created a slightly different SwingViewer - my version takes all
dependencies via constructors (which I think is neater than using setters to
define dependencies). I've also defined internally a default view map as I think
it's OK for us to assume default views (e.g. text entry fields) and then allow
the developer to override it. I've also changed it so the list of registered
classes to be passed in. All of this is by way of a test to see how simple we
can make application setup - I'd appreciate your comments. My
ConfigurableSwingViewer isn't as functional as yours - I originally based the
code on yours but then realised I didn't need to reinvent the wheel, just show
how it could be invoked.
Next up I want to create a bootstrapper that just uses Java code...
sam
http://www.magpiebrain.com/
|
|
From: Greg S. <ste...@on...> - 2004-07-03 22:42:06
|
sam...@ma... wrote: >Quoting Greg Steckman <ste...@on...>: > > > >>>If we have an abstratc notion of a ClassRegistry, the SwingViewer could look >>> >>> >>at >> >> >>>this rather than the database. Then along with the other things, we >>> >>> >>configure a >> >> >>>ClassRegistry. Why don't I look at implementing that code? >>> >>> >>> >>I guess the question is, should the ClassRegistry be any different than >>the standard persistence mechanism? It would seem easier to use the >>standard persistence mechanism, since it's already used to store and >>retrieve data. Then the same framework can be used everywhere to >>edit/view the classes as regular objects. >> >> > >The problem with this is that developers will always have to seed their >persistence mechanism which increases the amount of work. In fact they'll have >to do that before the deployment of every new version of the software that >introduces new classes. I really want figleaf (or whatever we call it!) to >emphasise how easy it is to drop the code in and run. What benifits does having >the classes registration handled by the persistence mechanism have over handling >it like standard application configuration? > > > I guess I take the seeding problem as a given. The more we can avoid seeding then great. But it seems like there is always some startup data needed - like when you install a new OS it needs to ask you for a root password. The task becomes how to make the data initialization as simple as possible. Also, we need to decide where to draw the line between what system required data is stored in configuration files and what is stored in the persistence mechanism. Greg |
|
From: <sam...@ma...> - 2004-07-03 22:36:37
|
Quoting Greg Steckman <ste...@on...>: > I think a configuraion API is a good idea - it would be convenient to be > able to configure in ways other than an XML file (like getting it from a > database or programmatically). However, I wouldn't consider it a > critical feature at this time. Our interfaces are likely to change > rapidly at the beginning, and therefore the configuration interface will > have to keep changing also. That makes just changing an XML file a good > approach for now, particularly since I can just add any property to the > xml file and Spring automatically sets it with the correct > values/references. An abstracted layer isn't that much work, but as you say lets concentrate on other things for now - lets get something running! > What about the Introspector work? I need to put my proxy code back in - its usable right now as is(put any object into an InformativeFactoryImpl and get a valid Informative object back), but returned objects don't have the same interface as those passed in. It should be good enough for you to use right now though. I hope to have the proxy code done by tomorrow evening. sam http://www.magpiebrain.com/ |
|
From: <sam...@ma...> - 2004-07-03 22:31:56
|
Quoting Greg Steckman <ste...@on...>: > >I think we need to abstract out the reliance on Spring. Using an > >ApplicationContext.xml is fine if you are using spring, but it would be nice > if > >we couls have a unified API for configuring the layers - the default > >Bootstrapper would use spring, but you could just as easily use a different > >implementation. > > > > > > > The benefits of Spring are the dependency injection and implementation > of a lot of useful classes in the areas of AOP, transactions, and > persistence. It isn't required to configure Spring with an xml file. > That's just the method I've chosen now because it was fastest to get > something running. We should be able to put our own configuration > mechanism in place and still use Spring for various things. I know in > its manual it mentions which interface/class to implement to get > configuration information from somewhere other than an XML file. I understand that - but the ability to use something other than Spring makes testing easier (it means you don't have to invoke Spirng when attemtping to Unit test some things). Spring is a good fit for what we want, but thins can change - by keeping any association abstract we make transition to something else later on a lot easier. > >>So, the developer doesn't have to write any main class! The bootstrapper > >>talks to Spring to handle the dependency injection and "running" the > >>class specified with the -bean command line parameter. > >Which I like! Not sure if this will apply as easily with a client-server > >application though. > > > > > > > It should work. Just swap out the bean definitions with those that do > something else: client work or server work. Yep - I guess we'll worry about that when it happens > >As you say the problem is getting this information into the system in the > first > >instance. Again pre-seeding the database is one potential mechanism for > getting > >information into figleaf, but how about we keep it simple for now? Lets add > a > >method to Bootstrapper registerClass, which we could even configure using a > >Spring and its ApplicationContext context file. Personally I would love to > be > >able to run an app without having to edit any config files and just specify > >everything using a simple piece Java code, and have config files call this > API - > >it makes it easy to test, and many people are happy configuring applications > in > >code. > > > I don't think class registration and configuration are necessarily the > same thing. The reason is because class accessibility should integrate > with the security mechanism. By having a class that describes classes, > it enables all of the functionality that Informative has but at a sort > of meta-level. Agree > So far to bootstrap the system you have to insert 1 record in the > database for the core InformativeDescriptor that describes itself. After > that the GUI can be used to create the rest of the classes in the > system. I hope to have that working very soon. Which sounds good, but I'd still like an abstract ClassRegistry-type thing so people don't have to seed their persistence mechanism. > > > >If we have an abstratc notion of a ClassRegistry, the SwingViewer could look > at > >this rather than the database. Then along with the other things, we > configure a > >ClassRegistry. Why don't I look at implementing that code? > > > I guess the question is, should the ClassRegistry be any different than > the standard persistence mechanism? It would seem easier to use the > standard persistence mechanism, since it's already used to store and > retrieve data. Then the same framework can be used everywhere to > edit/view the classes as regular objects. The problem with this is that developers will always have to seed their persistence mechanism which increases the amount of work. In fact they'll have to do that before the deployment of every new version of the software that introduces new classes. I really want figleaf (or whatever we call it!) to emphasise how easy it is to drop the code in and run. What benifits does having the classes registration handled by the persistence mechanism have over handling it like standard application configuration? sam http://www.magpiebrain.com/ |
|
From: Greg S. <ste...@on...> - 2004-07-03 22:00:02
|
sam...@ma... wrote: >As I see it, at this stage of the game we need to configure the following things: > >1. Which persistence mechanism to use >2. Which UI mechanism to use >3. Which Object manager to use >4. Which classes to use > >How about an ApplicationConfiguration interface which defines the folowing methods: > >getPersistenceMechanism() >getUIMechanism() >getObjectManager() >getRegisteredClasses() > >The default ApplicationConfiguration implementation will use Spring - it will be >up to the bootstrapper class (or whatever) to invoke the correct configuration. >Even if we do use Spring, it would be nice to keep any configuration files as >simple as possible - the AppicationContext files can get a little verbose, so we >may want to roll our own configuration file. I can code up an implementation >that uses Spring's configuration file behind the scenes if you want - it will >just act as an abstracted layer for the code you already have. I'll probably >also code an implementation which allows the user to code the configuration >directly. > >sam >http://www.magpiebrain.com/ > > > > I think a configuraion API is a good idea - it would be convenient to be able to configure in ways other than an XML file (like getting it from a database or programmatically). However, I wouldn't consider it a critical feature at this time. Our interfaces are likely to change rapidly at the beginning, and therefore the configuration interface will have to keep changing also. That makes just changing an XML file a good approach for now, particularly since I can just add any property to the xml file and Spring automatically sets it with the correct values/references. What about the Introspector work? Greg |
|
From: Greg S. <ste...@on...> - 2004-07-03 21:53:49
|
sam...@ma... wrote: >Quoting Greg Steckman <ste...@on...>: > > > >>Have a look at ApplicationContext.xml (the Spring config file), now in >>the /conf directory, and also Bootstrapper.java. The >>ApplicationContext.xml specifies which persistence implementation to >>use, which ObjectManager class to use, and which viewer to use. The >>Bootstrapper takes command line arguments to tell it which "bean" to run >>(SwingViewer is runnable). I also added a run.sh script last night, >>which will let you see how it all fits together. I got it fired up last >>night. >> >> > >I think we need to abstract out the reliance on Spring. Using an >ApplicationContext.xml is fine if you are using spring, but it would be nice if >we couls have a unified API for configuring the layers - the default >Bootstrapper would use spring, but you could just as easily use a different >implementation. > > > The benefits of Spring are the dependency injection and implementation of a lot of useful classes in the areas of AOP, transactions, and persistence. It isn't required to configure Spring with an xml file. That's just the method I've chosen now because it was fastest to get something running. We should be able to put our own configuration mechanism in place and still use Spring for various things. I know in its manual it mentions which interface/class to implement to get configuration information from somewhere other than an XML file. >>So, the developer doesn't have to write any main class! The bootstrapper >>talks to Spring to handle the dependency injection and "running" the >>class specified with the -bean command line parameter. >> >> > > >Which I like! Not sure if this will apply as easily with a client-server >application though. > > > It should work. Just swap out the bean definitions with those that do something else: client work or server work. >>One missing piece of the puzzle: registration of classes. I made an >>InformativeDescriptor interface who's job is to describe an Informative >>class. There is an InformativeDescriptorImpl as well. All the developer >>needs to do is pre-seed the database (or whatever the persistence >>mechanism is) with InformativeDescriptor records. >> >> > >As you say the problem is getting this information into the system in the first >instance. Again pre-seeding the database is one potential mechanism for getting >information into figleaf, but how about we keep it simple for now? Lets add a >method to Bootstrapper registerClass, which we could even configure using a >Spring and its ApplicationContext context file. Personally I would love to be >able to run an app without having to edit any config files and just specify >everything using a simple piece Java code, and have config files call this API - >it makes it easy to test, and many people are happy configuring applications in >code. > > > I don't think class registration and configuration are necessarily the same thing. The reason is because class accessibility should integrate with the security mechanism. By having a class that describes classes, it enables all of the functionality that Informative has but at a sort of meta-level. So far to bootstrap the system you have to insert 1 record in the database for the core InformativeDescriptor that describes itself. After that the GUI can be used to create the rest of the classes in the system. I hope to have that working very soon. >>Right now, when the SwingViewer starts it searches for all >>InformativeDescriptor's in the database, and shows those. The >>InformativeDescriptor has a "newInstance" method that the UI will use to >>allow the user to create a new instance of the class described by the >>InformativeDescriptor. In a future implementation when we have logins, I >>believe the set of InformativeDescriptors retrieved should be dependent >>on the user, so different users can have access to different classes. >>And then with a security layer it can control if a user can create new >>instances of a class, etc. >> >> > >If we have an abstratc notion of a ClassRegistry, the SwingViewer could look at >this rather than the database. Then along with the other things, we configure a >ClassRegistry. Why don't I look at implementing that code? > > > > I guess the question is, should the ClassRegistry be any different than the standard persistence mechanism? It would seem easier to use the standard persistence mechanism, since it's already used to store and retrieve data. Then the same framework can be used everywhere to edit/view the classes as regular objects. Greg |
|
From: Greg S. <ste...@on...> - 2004-07-03 21:41:37
|
sam...@ma... wrote: >A quick question. I can see that you directly run the SwingView - does it make >sense to move the run method into the Viewer interface, or at least move it into >a RunnableViewer interface? That would make a Bootstrapper more robust (as it >currently stands, if the UI mechanism doesn't implement run they'll be a >MethodNotFoundException). > >sam >http://www.magpiebrain.com/ > > > > > The bootstrapper isn't directly tied to the viewer at all. I thought the bootstrapper could also be used to run things other than a viewer. For instance, by defining a "Server" bean in the config file and then using "-bean Server" on the commandline the bootstrapper would run a server. The only limitation is that the bean specified with -bean must implement Runnable. Greg |
|
From: Greg S. <ste...@on...> - 2004-07-03 21:38:25
|
sam...@ma... wrote: >Quoting Greg Steckman <ste...@on...>: > > > >>I had a look at the maven generated ant build file and for some reason >>it was hard-coding paths in from my system. I couldn't find any >>properties or anything to alter that behavior...so that's nowhere for >>now. I have been adding lots of jars to the lib directory, and refining >>the Maven file. >> >> > >I really like the idea of maven as an aid for developers of the project, but >like ant for other reasons. How about you manage the maven build, and I manage >the ant build? That way all our prospective users are happy :-) > > > Sounds good. Greg |
|
From: <sam...@ma...> - 2004-07-03 21:16:57
|
A quick question. I can see that you directly run the SwingView - does it make sense to move the run method into the Viewer interface, or at least move it into a RunnableViewer interface? That would make a Bootstrapper more robust (as it currently stands, if the UI mechanism doesn't implement run they'll be a MethodNotFoundException). sam http://www.magpiebrain.com/ |
|
From: <sam...@ma...> - 2004-07-03 21:11:02
|
As I see it, at this stage of the game we need to configure the following things: 1. Which persistence mechanism to use 2. Which UI mechanism to use 3. Which Object manager to use 4. Which classes to use How about an ApplicationConfiguration interface which defines the folowing methods: getPersistenceMechanism() getUIMechanism() getObjectManager() getRegisteredClasses() The default ApplicationConfiguration implementation will use Spring - it will be up to the bootstrapper class (or whatever) to invoke the correct configuration. Even if we do use Spring, it would be nice to keep any configuration files as simple as possible - the AppicationContext files can get a little verbose, so we may want to roll our own configuration file. I can code up an implementation that uses Spring's configuration file behind the scenes if you want - it will just act as an abstracted layer for the code you already have. I'll probably also code an implementation which allows the user to code the configuration directly. sam http://www.magpiebrain.com/ |
|
From: <sam...@ma...> - 2004-07-03 20:54:12
|
Quoting Greg Steckman <ste...@on...>: > It's OK with me if you add tests for my code. If I have cause to edit your code I'll certainly add tests, and depending how much time I have over the next few days I might add some for yours too. > I had a look at the maven generated ant build file and for some reason > it was hard-coding paths in from my system. I couldn't find any > properties or anything to alter that behavior...so that's nowhere for > now. I have been adding lots of jars to the lib directory, and refining > the Maven file. I really like the idea of maven as an aid for developers of the project, but like ant for other reasons. How about you manage the maven build, and I manage the ant build? That way all our prospective users are happy :-) sam http://www.magpiebrain.com/ |
|
From: <sam...@ma...> - 2004-07-03 20:51:07
|
Quoting Greg Steckman <ste...@on...>: > sam...@ma... wrote: > > >Well, my code handles objects which haven't implemented Informative (in > fact > >thats what 80% of what I've done so far does) so we don't have to worry > about > >that. I actually believe one of the big selling points is the lack of work > a > >developer has to do to get up and running, for that reason I'd like for the > 0.1 > >release for the developer to drop a vanilla pojo domain model in and have to > do > >no work for it to run. > > > > > That would be great to have working. > <snip> > > > Have a look at ApplicationContext.xml (the Spring config file), now in > the /conf directory, and also Bootstrapper.java. The > ApplicationContext.xml specifies which persistence implementation to > use, which ObjectManager class to use, and which viewer to use. The > Bootstrapper takes command line arguments to tell it which "bean" to run > (SwingViewer is runnable). I also added a run.sh script last night, > which will let you see how it all fits together. I got it fired up last > night. I think we need to abstract out the reliance on Spring. Using an ApplicationContext.xml is fine if you are using spring, but it would be nice if we couls have a unified API for configuring the layers - the default Bootstrapper would use spring, but you could just as easily use a different implementation. > So, the developer doesn't have to write any main class! The bootstrapper > talks to Spring to handle the dependency injection and "running" the > class specified with the -bean command line parameter. Which I like! Not sure if this will apply as easily with a client-server application though. > One missing piece of the puzzle: registration of classes. I made an > InformativeDescriptor interface who's job is to describe an Informative > class. There is an InformativeDescriptorImpl as well. All the developer > needs to do is pre-seed the database (or whatever the persistence > mechanism is) with InformativeDescriptor records. As you say the problem is getting this information into the system in the first instance. Again pre-seeding the database is one potential mechanism for getting information into figleaf, but how about we keep it simple for now? Lets add a method to Bootstrapper registerClass, which we could even configure using a Spring and its ApplicationContext context file. Personally I would love to be able to run an app without having to edit any config files and just specify everything using a simple piece Java code, and have config files call this API - it makes it easy to test, and many people are happy configuring applications in code. > Right now, when the SwingViewer starts it searches for all > InformativeDescriptor's in the database, and shows those. The > InformativeDescriptor has a "newInstance" method that the UI will use to > allow the user to create a new instance of the class described by the > InformativeDescriptor. In a future implementation when we have logins, I > believe the set of InformativeDescriptors retrieved should be dependent > on the user, so different users can have access to different classes. > And then with a security layer it can control if a user can create new > instances of a class, etc. If we have an abstratc notion of a ClassRegistry, the SwingViewer could look at this rather than the database. Then along with the other things, we configure a ClassRegistry. Why don't I look at implementing that code? sam http://www.magpiebrain.com/ |
|
From: Greg S. <ste...@on...> - 2004-07-03 18:45:38
|
sam...@ma... wrote: >OK, I've merged in my code - it now sits upnder the same net/sourceforge/figleaf >package. The only thing of the original code that I've backed out is that >Informative no longer implements Validatable, this is purely to reduce the >amount of changes in my current code. The issues we still have to resolve >however including: > >1. Does my InformativeFactory have to return proxies that implement both >Informative and still have the original objects interface? I can't see how this >is of benift to the UI > > From the other e-mail it looks like we agree on the need for Proxies. >2. If the user decides to implement Observalbe themselves, I pretty much ignore >it - I need to treat this in the same way as the user defining their own >ClassDescriptor implementations > > Yep. >3. I've noticed that you've defined Hibernate persistence information for the >Informative interface, but I'm not sure this is needed. If we provide the >implementation then its autogenerated each time the application is run, if the >user defines it any persistence of their own classes has to be up to them. > > I made a hibernate mapping file for InformativeDescriptorImpl, but not for Informative as far as I remember. >4. Do we need to include the license description at the top of each file? Some >files do, others don't - we probably need to decide on a consistent approach. > > My intent for now was to put it in every file, but I don't really know what is sufficient. Maybe just the copyright line? >I've added @version $Id$ tags to all code I've touched - this is handy when >tracking through code (CVS expands this to display version information on checkin). > > Good idea. I'll start doing it too. >I'm now going to look over what I've done and tidy things up a little, and will >then look either at beefing up our tests (I might add some tests for your code >if that's OK?), the ant build script, or on some simple approaches for tying the >layers together (so perhaps Pico, but probably Spring). > > > It's OK with me if you add tests for my code. I had a look at the maven generated ant build file and for some reason it was hard-coding paths in from my system. I couldn't find any properties or anything to alter that behavior...so that's nowhere for now. I have been adding lots of jars to the lib directory, and refining the Maven file. Greg |
|
From: Greg S. <ste...@on...> - 2004-07-03 18:37:43
|
sam...@ma... wrote:
>>>
>>>
>>For now I'd even settle for just requiring objects to implement
>>Informative completely themselves and get the persistence and UI layers
>>worked out. It'll then be a functional platform to some extent. That's
>>the approach I've taken so far.
>>
>>
>
>Well, my code handles objects which haven't implemented Informative (in fact
>thats what 80% of what I've done so far does) so we don't have to worry about
>that. I actually believe one of the big selling points is the lack of work a
>developer has to do to get up and running, for that reason I'd like for the 0.1
>release for the developer to drop a vanilla pojo domain model in and have to do
>no work for it to run.
>
>
That would be great to have working.
>My todo list once I've put proxies back in is a little sparse - might thought
>was that I should look at our API for typing the layers together. We want an API
>that lets us configure Spring (or Pico or whatever). I saw a bit of code like
>this written by the developer:
>
>public class MyFigleafApplication extends FigleafApplication {
> public void setup() {
> setPersistenceMechanism(new HibernateImpl("config.hbm.xml"));
> setUIMechanism(new SwingImpl());
> ...
> registerClass(MyClass.class);
> registerClass(AnotherClass.class);
> }
>
> public static void main(String[] args) {
> new MyFigleafApplication().run();
> }
>}
>
>We may want to use config files for this later on, but for now doing it using
>Java code makes it easy to test and lets us concentrate on the important stuff.
>What do you think?
>
>
>
Have a look at ApplicationContext.xml (the Spring config file), now in
the /conf directory, and also Bootstrapper.java. The
ApplicationContext.xml specifies which persistence implementation to
use, which ObjectManager class to use, and which viewer to use. The
Bootstrapper takes command line arguments to tell it which "bean" to run
(SwingViewer is runnable). I also added a run.sh script last night,
which will let you see how it all fits together. I got it fired up last
night.
So, the developer doesn't have to write any main class! The bootstrapper
talks to Spring to handle the dependency injection and "running" the
class specified with the -bean command line parameter.
One missing piece of the puzzle: registration of classes. I made an
InformativeDescriptor interface who's job is to describe an Informative
class. There is an InformativeDescriptorImpl as well. All the developer
needs to do is pre-seed the database (or whatever the persistence
mechanism is) with InformativeDescriptor records.
Right now, when the SwingViewer starts it searches for all
InformativeDescriptor's in the database, and shows those. The
InformativeDescriptor has a "newInstance" method that the UI will use to
allow the user to create a new instance of the class described by the
InformativeDescriptor. In a future implementation when we have logins, I
believe the set of InformativeDescriptors retrieved should be dependent
on the user, so different users can have access to different classes.
And then with a security layer it can control if a user can create new
instances of a class, etc.
Greg
|
|
From: <sam...@ma...> - 2004-07-03 18:19:51
|
Quoting Greg Steckman <ste...@on...>:
> Hi Sam,
> >Do, but why does it need to be an instanceof? Surely the UI wuold just call
> >'getProperties' to expose the right views, which does it need to know the
> >specific class?
> >
> >
> >
>
> The UI will in some cases take one object, that is visible, and pass it
> to another object that is visible as a method parameter or to a property
> setter. If the first object isn't of the expected type, there will be a
> problem. I planned on having the UI inspect the class/interfaces objects
> implement when determining if they matched the types expected. If the
> object the UI has is really a delegate that doesn't implement all the
> interfaces and class hierarchy of the real class, then there will have
> to be extra code like "instance.getRealInstance()". But now that "real"
> object which will be used to set a property, won't implement Informative
> and therefore property set calls made to it by the second class won't
> have events fired, for example.
Of course you're right - I'll put the proxies back in.
> >
> >Which I have - I also have it implementing Observable. I would say that for
> the
> >first version we provide the implementation of Observable and add the code
> later
> >on which will allow users to define their own.
> >
> >
> >
> For now I'd even settle for just requiring objects to implement
> Informative completely themselves and get the persistence and UI layers
> worked out. It'll then be a functional platform to some extent. That's
> the approach I've taken so far.
Well, my code handles objects which haven't implemented Informative (in fact
thats what 80% of what I've done so far does) so we don't have to worry about
that. I actually believe one of the big selling points is the lack of work a
developer has to do to get up and running, for that reason I'd like for the 0.1
release for the developer to drop a vanilla pojo domain model in and have to do
no work for it to run.
My todo list once I've put proxies back in is a little sparse - might thought
was that I should look at our API for typing the layers together. We want an API
that lets us configure Spring (or Pico or whatever). I saw a bit of code like
this written by the developer:
public class MyFigleafApplication extends FigleafApplication {
public void setup() {
setPersistenceMechanism(new HibernateImpl("config.hbm.xml"));
setUIMechanism(new SwingImpl());
...
registerClass(MyClass.class);
registerClass(AnotherClass.class);
}
public static void main(String[] args) {
new MyFigleafApplication().run();
}
}
We may want to use config files for this later on, but for now doing it using
Java code makes it easy to test and lets us concentrate on the important stuff.
What do you think?
sam
http://www.magpiebrain.com/
|
|
From: <sam...@ma...> - 2004-07-03 16:13:41
|
OK, I've merged in my code - it now sits upnder the same net/sourceforge/figleaf package. The only thing of the original code that I've backed out is that Informative no longer implements Validatable, this is purely to reduce the amount of changes in my current code. The issues we still have to resolve however including: 1. Does my InformativeFactory have to return proxies that implement both Informative and still have the original objects interface? I can't see how this is of benift to the UI 2. If the user decides to implement Observalbe themselves, I pretty much ignore it - I need to treat this in the same way as the user defining their own ClassDescriptor implementations 3. I've noticed that you've defined Hibernate persistence information for the Informative interface, but I'm not sure this is needed. If we provide the implementation then its autogenerated each time the application is run, if the user defines it any persistence of their own classes has to be up to them. 4. Do we need to include the license description at the top of each file? Some files do, others don't - we probably need to decide on a consistent approach. I've added @version $Id$ tags to all code I've touched - this is handy when tracking through code (CVS expands this to display version information on checkin). I'm now going to look over what I've done and tidy things up a little, and will then look either at beefing up our tests (I might add some tests for your code if that's OK?), the ant build script, or on some simple approaches for tying the layers together (so perhaps Pico, but probably Spring). sam http://www.magpiebrain.com/ |
|
From: Greg S. <ste...@on...> - 2004-07-03 16:06:18
|
Hi Sam, sam...@ma... wrote: >Quoting Greg Steckman <ste...@on...>: > > > >>sam...@ma... wrote: >> >> >> >>The object returned must be an "instanceof" the object I wanted. Would >>this do that? >> >> > >Do, but why does it need to be an instanceof? Surely the UI wuold just call >'getProperties' to expose the right views, which does it need to know the >specific class? > > > The UI will in some cases take one object, that is visible, and pass it to another object that is visible as a method parameter or to a property setter. If the first object isn't of the expected type, there will be a problem. I planned on having the UI inspect the class/interfaces objects implement when determining if they matched the types expected. If the object the UI has is really a delegate that doesn't implement all the interfaces and class hierarchy of the real class, then there will have to be extra code like "instance.getRealInstance()". But now that "real" object which will be used to set a property, won't implement Informative and therefore property set calls made to it by the second class won't have events fired, for example. >If by non-property methods you mean the 'action' type methods from NakedObjects >this is still not a problem - we can add in the concept of these via your >message descriptors to the object returned from the factory > > That's what I meant. > > > >>Currently there are interfaces defined which allow the following: >> >>Informative myInformative=theObjectManager.newInstance(com.foo.bar.class); >>PropertyDescriptors[] >>pd=myInformative.getClassDescriptor().getPropertyDescriptors(); >>MethodDescriptors[] >>md=myInformative.getClassDescriptor().getMethodDescriptors(); >>myInformative.getClassDesctiptor().getDisplayName(); >>myInformative.getClassDesctiptor().getDescription(); >>etc. >> >>I think this essentially is the same as what you are proposing. All the >>"magic" happens in the ObjectManager.newInstance call (and other methods >>that return Informatives). But the following constraints should be >>maintained: >> >>myInformative instanceof Informative evaluates to true >>myInformative instanceof com.foo.bar evaluates to true >> >> > >Again, why does the UI need to know of the actual underlying class? > > See above. > > > >>The array of PropertyDescriptors is not a problem (at least for a UI >>generator) because it will add them all to the UI (in the order as >>returned by the object). There is no need for the UI code to invoke a >>property by name. It maintains references to the PropertyDescriptor and >>then just invokes the readMethod or writeMethod when required. >> >> > >So the PropertyDescriptor has readMethod/writeMethod? If the user can define >their own PRopertyDescriptors (as we have planned) we are then allowing them to >change what is invoked. Also, I thought that your PropertyDesciptor is >class-sepcific rather than instance-specific - in which case you'll have to pass >in the actual instance to invoke the read/write method, which leads to this: > >bean.getProperty(propertyName).invokeGetter(bean); > >which looks a little strange. However I should remember what I said earlier - >lets settle on the simple cases to get a version out... > > > Check the PropertyDescriptor interface - it's pretty simple, allowing to get the property read and write Methods. I more or less took inspiration from the Java Beans API (java.beans...) but using a lot more interfaces for added implementation flexibility and stripping out what I thought we didn't need. >>I almost have a whole slice working with objects that implement >>Informative on their own. The only missing piece would be to implement >>an Introspector that knows how to make a proxy that implements >>Informative given an object instance that does not. >> >> > >Which I have - I also have it implementing Observable. I would say that for the >first version we provide the implementation of Observable and add the code later >on which will allow users to define their own. > > > For now I'd even settle for just requiring objects to implement Informative completely themselves and get the persistence and UI layers worked out. It'll then be a functional platform to some extent. That's the approach I've taken so far. Greg |
|
From: <sam...@ma...> - 2004-07-03 09:52:15
|
Quoting Greg Steckman <ste...@on...>: > sam...@ma... wrote: > > >I had a major brainwave last night and realised we don't need proxies at > all. > >Here is my new proposed workflow for introducing developer-defined beans > into > >the system. > > > >1. The ProxyFactory (now needs to be renamed) gets given an object > >2. It invokes an ObjectIntrospector to retrieve an Informative > implementation > >3. It creates an implementation of the new interface Bean (needs a rename?) > >which implements Informative and Observable. In addition it defines two new > methods: > > > >Object getProperty(String propertyName); > > > >void setProperty(String propertyName, Object propertyValue); > > > >These methods fire change events accordingly without any need for proxied > method > >interception. > > > >4. This is returned to the UI layer (or whatever). > > > The object returned must be an "instanceof" the object I wanted. Would > this do that? Do, but why does it need to be an instanceof? Surely the UI wuold just call 'getProperties' to expose the right views, which does it need to know the specific class? > > > >5. To interact with this developer defined object, the UI first gets a list > of > >properties to expose them (which comes from the underlying Informative > >implementation). To invoke a method, it calls getProperty() or > setProperty() > >with the relevent property name. > > > >This removes the need for all proxies, results in easier to test, less > >complicaed code, and I think gives the UI evervything it needs. We may > still > >need proxies for remoting/securirty/validation or whatever, but for the > moment > >it doesn't look like we need to. > > > > How does the UI then access non-property methods of the object? The > object needs to be able to expose to the UI actions that can be invoked > by the user. That is the main purpose of the MethodDescriptors. > If by non-property methods you mean the 'action' type methods from NakedObjects this is still not a problem - we can add in the concept of these via your message descriptors to the object returned from the factory > > Currently there are interfaces defined which allow the following: > > Informative myInformative=theObjectManager.newInstance(com.foo.bar.class); > PropertyDescriptors[] > pd=myInformative.getClassDescriptor().getPropertyDescriptors(); > MethodDescriptors[] > md=myInformative.getClassDescriptor().getMethodDescriptors(); > myInformative.getClassDesctiptor().getDisplayName(); > myInformative.getClassDesctiptor().getDescription(); > etc. > > I think this essentially is the same as what you are proposing. All the > "magic" happens in the ObjectManager.newInstance call (and other methods > that return Informatives). But the following constraints should be > maintained: > > myInformative instanceof Informative evaluates to true > myInformative instanceof com.foo.bar evaluates to true Again, why does the UI need to know of the actual underlying class? > The array of PropertyDescriptors is not a problem (at least for a UI > generator) because it will add them all to the UI (in the order as > returned by the object). There is no need for the UI code to invoke a > property by name. It maintains references to the PropertyDescriptor and > then just invokes the readMethod or writeMethod when required. So the PropertyDescriptor has readMethod/writeMethod? If the user can define their own PRopertyDescriptors (as we have planned) we are then allowing them to change what is invoked. Also, I thought that your PropertyDesciptor is class-sepcific rather than instance-specific - in which case you'll have to pass in the actual instance to invoke the read/write method, which leads to this: bean.getProperty(propertyName).invokeGetter(bean); which looks a little strange. However I should remember what I said earlier - lets settle on the simple cases to get a version out... > > I almost have a whole slice working with objects that implement > Informative on their own. The only missing piece would be to implement > an Introspector that knows how to make a proxy that implements > Informative given an object instance that does not. Which I have - I also have it implementing Observable. I would say that for the first version we provide the implementation of Observable and add the code later on which will allow users to define their own. sam http://www.magpiebrain.com/ |
|
From: Greg S. <ste...@on...> - 2004-07-02 16:18:32
|
sam...@ma... wrote: >I had a major brainwave last night and realised we don't need proxies at all. >Here is my new proposed workflow for introducing developer-defined beans into >the system. > >1. The ProxyFactory (now needs to be renamed) gets given an object >2. It invokes an ObjectIntrospector to retrieve an Informative implementation >3. It creates an implementation of the new interface Bean (needs a rename?) >which implements Informative and Observable. In addition it defines two new methods: > >Object getProperty(String propertyName); > >void setProperty(String propertyName, Object propertyValue); > >These methods fire change events accordingly without any need for proxied method >interception. > >4. This is returned to the UI layer (or whatever). > The object returned must be an "instanceof" the object I wanted. Would this do that? > >5. To interact with this developer defined object, the UI first gets a list of >properties to expose them (which comes from the underlying Informative >implementation). To invoke a method, it calls getProperty() or setProperty() >with the relevent property name. > >This removes the need for all proxies, results in easier to test, less >complicaed code, and I think gives the UI evervything it needs. We may still >need proxies for remoting/securirty/validation or whatever, but for the moment >it doesn't look like we need to. > How does the UI then access non-property methods of the object? The object needs to be able to expose to the UI actions that can be invoked by the user. That is the main purpose of the MethodDescriptors. > >Changes to support this: > >* The ProxyFactory/CglibProxyFactory will become a BeanFactory/BeanFactoryImpl. >The existing getProxy becomes makeBean > >* Property becomes your PropertyDescriptor > >* Mutable becomes Observable > >So now you can call: > > Bean bean = beanFactory.makeBean(developerDefinedObject); > ... > bean.getProperties(); > bean.getName(); > bean.getDescription(); > ... > bean.addChangeListener(); > bean.removeChangeListener(); > ... > Object retVal = bean.getProperty(propertyName); > bean.setProperty(propertyName, newValue); > >Further down the line getProperty and setProperty can throw validation >exceptions, or we can add an isValidPropertyValue() method or something. > >What do you think? > >sam > > > > Currently there are interfaces defined which allow the following: Informative myInformative=theObjectManager.newInstance(com.foo.bar.class); PropertyDescriptors[] pd=myInformative.getClassDescriptor().getPropertyDescriptors(); MethodDescriptors[] md=myInformative.getClassDescriptor().getMethodDescriptors(); myInformative.getClassDesctiptor().getDisplayName(); myInformative.getClassDesctiptor().getDescription(); etc. I think this essentially is the same as what you are proposing. All the "magic" happens in the ObjectManager.newInstance call (and other methods that return Informatives). But the following constraints should be maintained: myInformative instanceof Informative evaluates to true myInformative instanceof com.foo.bar evaluates to true The array of PropertyDescriptors is not a problem (at least for a UI generator) because it will add them all to the UI (in the order as returned by the object). There is no need for the UI code to invoke a property by name. It maintains references to the PropertyDescriptor and then just invokes the readMethod or writeMethod when required. I almost have a whole slice working with objects that implement Informative on their own. The only missing piece would be to implement an Introspector that knows how to make a proxy that implements Informative given an object instance that does not. Greg |
|
From: Greg S. <ste...@on...> - 2004-07-02 16:02:19
|
I think having the capability to modify behavior on a class-by-class basis is a good thing. There could be a good reason for someone to alter their implementation of Observable for a particular class. Since we can't foresee all possible usage scenarios, I wouldn't want to take that capability away from the developer. Of course with power comes responsibility: if they do it, they need to understand the consequences of how that object will behave in the application stack. I intentionally left the interface Informative without any methods of its own. It's basically a tag interface for knowing an object implements all three of Observable, ClassDescriptor, and Validatable (and perhaps we will add more later). My thought was if a class (or its helper) implements ClassDescriptor and Validatable, then the Introspector would detect that and provide a default implementation of Observable for it, thereby creating a proxy that implemented Informative. So the class (or its helper, metadata, etc) could provide implementations for none, some, or all of the sub-interfaces of Informative, and the Introspector/ProxyFactory would do the right thing to make a proxy instance that implements Informative completely. Greg sam...@ma... wrote: >Do we really want that? My code does that for the developer - the UI will depend >on these events being properly fired in order to maintain system integrity, as >such I think its something that should be under our control. > >Quoting Greg Steckman <ste...@on...>: > > > >>Note that Informative extends Observable. So if you implement >>Informative, then it means you must also implement Observable. >> >>Also, not all methods will be called via Property objects. Consider >>those objects invoking methods directly on the object (that is, those >>that know nothing about the Informative interface). >> >>Greg >> >> > > > >sam >http://www.magpiebrain.com/ > > > |
|
From: <sam...@ma...> - 2004-07-02 08:35:03
|
I had a major brainwave last night and realised we don't need proxies at all. Here is my new proposed workflow for introducing developer-defined beans into the system. 1. The ProxyFactory (now needs to be renamed) gets given an object 2. It invokes an ObjectIntrospector to retrieve an Informative implementation 3. It creates an implementation of the new interface Bean (needs a rename?) which implements Informative and Observable. In addition it defines two new methods: Object getProperty(String propertyName); void setProperty(String propertyName, Object propertyValue); These methods fire change events accordingly without any need for proxied method interception. 4. This is returned to the UI layer (or whatever). 5. To interact with this developer defined object, the UI first gets a list of properties to expose them (which comes from the underlying Informative implementation). To invoke a method, it calls getProperty() or setProperty() with the relevent property name. This removes the need for all proxies, results in easier to test, less complicaed code, and I think gives the UI evervything it needs. We may still need proxies for remoting/securirty/validation or whatever, but for the moment it doesn't look like we need to. Changes to support this: * The ProxyFactory/CglibProxyFactory will become a BeanFactory/BeanFactoryImpl. The existing getProxy becomes makeBean * Property becomes your PropertyDescriptor * Mutable becomes Observable So now you can call: Bean bean = beanFactory.makeBean(developerDefinedObject); ... bean.getProperties(); bean.getName(); bean.getDescription(); ... bean.addChangeListener(); bean.removeChangeListener(); ... Object retVal = bean.getProperty(propertyName); bean.setProperty(propertyName, newValue); Further down the line getProperty and setProperty can throw validation exceptions, or we can add an isValidPropertyValue() method or something. What do you think? sam |
|
From: <sam...@ma...> - 2004-07-02 08:24:44
|
Do we really want that? My code does that for the developer - the UI will depend on these events being properly fired in order to maintain system integrity, as such I think its something that should be under our control. Quoting Greg Steckman <ste...@on...>: > Note that Informative extends Observable. So if you implement > Informative, then it means you must also implement Observable. > > Also, not all methods will be called via Property objects. Consider > those objects invoking methods directly on the object (that is, those > that know nothing about the Informative interface). > > Greg sam http://www.magpiebrain.com/ |