Compile java sources inside J2EE component

S

Stefan Siegl

Hello,

For my master thesis I have to create a customer relationship management
system (CRM). The final program should be a J2EE component. The
interesting part of this system is that the user can specify the data
schema (model) of the CRM system at runtime. To define this model I
created a metamodel. In order to allow an easy access to the model, I
will generate java source classes according to the model (that is
defined as instances of the meta classes). One problem is that the user
is allowed to change the model at runtime, meaning that the source code
files have to be recreated and compiled again.

So much for the introduction ;). After creating the source files I need
to compile them at runtime, is there a possibility to do so?

As I said before if the model changes, the new source code files need to
be compiled again. Is there a way to "unload" possible classes that were
created for the last model, so that there won't be a clash with the
newly created classes?

Any suggestions?
Best regards,
Stefan
 
A

Andrew Thompson

After creating the source files I need
to compile them at runtime, is there a possibility to do so?

Yes, but only by invoking classes for which
Sun issues no public documentation, and
reserves the right to change at any time.
As I said before if the model changes, the new source code files need to
be compiled again. Is there a way to "unload" possible classes that were
created for the last model, so that there won't be a clash with the
newly created classes?

I am on unfamiliar ground here, but you
might try using a custom class loader,
and refreshing it.

Better suggestions are probably forthcoming.

But.. why does a CRM need to compile source
'on the fly', it seems like you might be
approaching the problem wrong. (And again,
I am not that experienced with the area,
but it has a strong whiff of 'overkill'.)
 
J

jungi

Andrew said:
Yes, but only by invoking classes for which
Sun issues no public documentation, and
reserves the right to change at any time.

Not only. You can also use
java.lang.Runtime.getRuntime().exec("javac", ...) or
java.lang.Runtime.getRuntime().exec("jikes", ...), see Runtime javadoc.
Other option is for example using KJC (part of Kopi
(http://www.dms.at/kopi/)) it was not too fast 1,5 year ago, but authors
improved it(i hope), and it had public API (should be still
public).You can maybe find other compilers for java by googling ;-)

--jungi
 
G

Gordon Beaton

However this Sun article showing how to use com.sun.tools.javac.Main
to compile code from within a Java program seems to imply that the
advice doesn't hold for the com.sun.* classes:

Ok I spoke too quickly, the article does seem to include a warning
about using those classes too, although I'm certain it didn't when I
first read it a year ago.

It does refer to an API expected in 1.5 though. Could this be it?

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Compiler.html

/gordon
 
C

Chris Uppal

Stefan said:
So much for the introduction ;). After creating the source files I need
to compile them at runtime, is there a possibility to do so?

Yes. You can invoke Sun's compiler directly (I can't remember the precise
class off-hand, but it's mentioned in another thread in this newsgroup today).
Andrew's warning is to be taken seriously, but I wouldn't let it worry /me/ --
I believe that Sun are intending to provide a public API to compilation soon
(and that it only missed 1.5 because of time pressure), so I'd hope that if Sun
do remove the private classes, then they'll replace them with something else
you can use. You can always fall back to using javac if it really becomes
necessary, anyway.

However, if /I/ were doing this then I think I'd look at the option of
interpreting the meta-model directly, rather than generating new classes. I
think that would be easier, and I can't imagine it causing performance
problems. Still, there's nothing wrong with generating classes, if that's
what appeals to you, so...
As I said before if the model changes, the new source code files need to
be compiled again. Is there a way to "unload" possible classes that were
created for the last model, so that there won't be a clash with the
newly created classes?

You need to load all the "disposable" classes through a specially created
classloader (the standard URLClassLoader, or whatever it's called, should work
OK, but you might want to write your own anyway). When you drop the reference
to the classloader, and when there are no more instances of the classes
themselves alive, then the classes will be removed from the runtime. When you
want to create a new batch of classes, you create a new classloader to load
them, so there's no interference with any defunct classes that might still be
hanging around.

You'll probably find it worthwhile to define a bunch of interfaces that are
/not/ disposable, and which the various generated classes implement. Otherwise
you'll have difficulty "talking about" instances of the disposable classes in
other contexts.

One thing that isn't helped by classloaders is migrating the state of the
system as it is modified. If you create a new "version" of a class, the
instances of the existing class won't be migrated. You'll have to transfer the
state of the system from the old collection of objects to the new. Somehow...

Again, I think that migration would probably be easier if you were interpreting
the meta-model, and that's one reason why I'd consider that first.

-- chris
 
S

Stefan Siegl

Andrew said:
Yes, but only by invoking classes for which
Sun issues no public documentation, and
reserves the right to change at any time.




I am on unfamiliar ground here, but you
might try using a custom class loader,
and refreshing it.

I hope this is possible, I will give it a try, but I suspect that it
will not be that easy. I just thought that it must be possible to unload
the classes, because other Java application can do it too, i.e. the
JBoss app server with its hotdeploy feature.
Better suggestions are probably forthcoming.

But.. why does a CRM need to compile source
'on the fly', it seems like you might be
approaching the problem wrong. (And again,
I am not that experienced with the area,
but it has a strong whiff of 'overkill'.)

The central requirement of the system is that the user should be allowed
to define his specific CRM model at runtime. Therefore a metamodel is
provided by me to define the general constructs a model can have (like a
class, associations, and so on). The model will then be represented by
instances of these metaclasses. based on this model the user is allowed
to insert/query/delete data.

The problem is that the handling of model is not easy if the model is
stored as meta instances, because then i do not have a nice connection
between the entered data and the model. That is why I wanted to have
java classes that represent this model and instances of this model to
represent the data. Using this approach I can directly check if the
rules of the models are kept within the offered data.
 
A

Andrew Thompson

Andrew's warning is to be taken seriously, but I wouldn't let it worry /me/ --

(chuckles) It did not slow me down.

I figure Sun would only change those classes
if they saw good reason to do so, and given
they have been in the same place/form through
a number of releases, it suggests they are happy
with them as is.

One thing that isn't helped by classloaders is migrating the state of the
system as it is modified. If you create a new "version" of a class, the
instances of the existing class won't be migrated.

At first I thought Serialize them, but then
it struck me that this is one case where
Sun's warning on serialization would become
relevant. The class files change.

XMLEncoder?
 
S

Stefan Siegl

Chris Uppal wrote:

Hi Chris, thanks for your thoughts about the topic :)
Stefan Siegl wrote:




Yes. You can invoke Sun's compiler directly (I can't remember the precise
class off-hand, but it's mentioned in another thread in this newsgroup today).
Andrew's warning is to be taken seriously, but I wouldn't let it worry /me/ --
I believe that Sun are intending to provide a public API to compilation soon
(and that it only missed 1.5 because of time pressure), so I'd hope that if Sun
do remove the private classes, then they'll replace them with something else
you can use. You can always fall back to using javac if it really becomes
necessary, anyway.

However, if /I/ were doing this then I think I'd look at the option of
interpreting the meta-model directly, rather than generating new classes. I
think that would be easier, and I can't imagine it causing performance
problems. Still, there's nothing wrong with generating classes, if that's
what appeals to you, so...

I also thought about that, but there are also drawbacks.

The model and the data is not tightly connected. If just have instances
of meta classes and data (inside generic DTO's with a HashMap that
stores key (=attribute name) and value (=value of the attribute)), I
still have to check if this data is valid according to the model. If I
would have classes I could use the Java Reflection and just try to set
these attributes according to the given generic DTO. The check will then
be done through the Reflection mechanism.

What I did not describe so far is that my meta model allows to add rules
to the model. This should provide the possiblity to put constraints on
the model (i.e. each employee be older than 18). During the code
generation I could create checks for these rules and inform the caller
using an exception if he does not stick to these rules. If I use the
meta model instances I additionally have to check these rules. An other
idea I had for rules is to allow derivation rules to define how derived
attributes are defined. This could also done with code generation but is
much more complex when just checking the metamodel.

The last thing is that the persistence will get a bit more complex.

But I will thing about that again. Perhaps the code generation,
compilation and unloading are much more complex so that this does not
justify that approach.
One thing that isn't helped by classloaders is migrating the state of the
system as it is modified. If you create a new "version" of a class, the
instances of the existing class won't be migrated. You'll have to transfer the
state of the system from the old collection of objects to the new. Somehow...

Again, I think that migration would probably be easier if you were interpreting
the meta-model, and that's one reason why I'd consider that first.

This class and object lifecycle is not directly part of my master
thesis, meaning that I do not have to provide a complete and working
solution for that (which does not mean, that I do not want to do that
*g*). Currently I was thinking that I will just store the database
storing the old data and create a new database for the new schema and
provide a way to read the old data and transfer them to the new schema.

Thanks again,
Stefan
 
A

Andrew Thompson

I hope this is possible, I will give it a try, but I suspect that it
will not be that easy.

Way no. It's p*ss easy. I defined my
own URLClassLoader that came to about
two dozen lines. Look at the example
in the JavaDocs for ClassLoader.. it
is almost there, as is.
 
A

Andrew Thompson

On Tue, 07 Sep 2004 12:01:39 +0200, Stefan Siegl wrote:

(A.T.)
....
The central requirement of the system ..

Whoop.. Whoa-up there. If nobody else in this
thread seems concerned with it, it suggests to
me I was wrong.

'..as you were.'
 
S

Sudsy

Stefan Siegl wrote:
What I did not describe so far is that my meta model allows to add rules
to the model. This should provide the possiblity to put constraints on
the model (i.e. each employee be older than 18). During the code
generation I could create checks for these rules and inform the caller
using an exception if he does not stick to these rules. If I use the
meta model instances I additionally have to check these rules. An other
idea I had for rules is to allow derivation rules to define how derived
attributes are defined. This could also done with code generation but is
much more complex when just checking the metamodel.
<snip>

I was half way through this paragraph when it hit me: you could do all
of this with XML Schema and a validating parser! You don't have to re-
invent the wheel and there are oodles of tools available. You could
probably even find an Eclipse plug-in for editing the Schema.
Just thowing out the idea for your consideration.
 
W

Will Hartung

The central requirement of the system is that the user should be allowed
to define his specific CRM model at runtime. Therefore a metamodel is
provided by me to define the general constructs a model can have (like a
class, associations, and so on). The model will then be represented by
instances of these metaclasses. based on this model the user is allowed
to insert/query/delete data.

The problem is that the handling of model is not easy if the model is
stored as meta instances, because then i do not have a nice connection
between the entered data and the model. That is why I wanted to have
java classes that represent this model and instances of this model to
represent the data. Using this approach I can directly check if the
rules of the models are kept within the offered data.

As others have mentioned, ClassLoaders are what you need here. You can
compile the code using either the "unsupported" sun classes, or forking a
javac command.

One other thought though, have you thought about implementing any of this in
an embedded scripting language?

Embedding Javascript or Python or Scheme is fairly trivial and they're a lot
more lax about having their objects gratuitously changed behind their backs.
They also have their own compiler/interpreters, so you just need to load the
source code and go rather than fighting with javac and ClassLoaders (instead
you get to fight with environments and what not with the embedded
language -- similar issues, but perhaps less complicated overall).

The real issue is if objects "leak out" of your custom ClassLoader, things
can get Weird really quickly.

Plus, technically, you're not supposed be playing games with ClassLoaders
and what not, at least not at the EJB tier (which has a very complicated
ClassLoader structure). Less of a problem in something like Tomcat.

I acknowledge that this is all a Master Thesis, and it doesn't need to be
bullet proof or production quality, etc, it just Needs To Work.

But I'd consider any of the several scripting languages in your project.

Regards,

Will Hartung
([email protected])
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top