Rewriting my tomcat LWRP, how best to group options?


#1

I am rewriting my tomcat lwrp and here is what I have in mind, partly
inspired by Andrea Campi’s work

tomcat “liferay” do
gc do
min "256m"
max "512m"
max_perm_size "256m"
algorithm "UseConcMarkSweepGC"
end
profiling do # JMX
port "98204"
ssl false
authentication false
end
datasource do
driver 'org.gjt.mm.mysql.Driver’
database 'name’
port 5678
username 'user’
password 'password’
max_active 1
max_idle 2
max_wait 3
end
ports dof
http 8080
https 8443 # defaults to nil and not used
ajp 8009
shutdown 8005
end

end

Commandline JVM options that don’t fit into the above api would have
to be crammed into an attribute like “additional_opts” or
node[‘tomcat’][‘additional_opts’]

the issue I have is whether to group the options to be used by java
virtual machine by function or by category.

Here is a different take on the tomcat lwrp, the uses a ‘jvm’ block
with the xx_opts and d_opts which correspond to -XX, and -D options.
thoughts?

tomcat “pentaho” do
path "/opt/pentaho"
version "7"
user "pentaho"
unpack_wars true
auto_deploy true
environment { }
jvm do
xms "256m"
xmx "512m"
max_perm_size "256m"
xx_opts { }
d_opts { }
additional_opts [ ]
end
datasource do
driver 'org.gjt.mm.mysql.Driver’
database 'name’
port 5678
username 'user’
password 'password’
max_active 1
max_idle 2
max_wait 3
end
ports do
http 8080
https 8443 # defaults to nil and not used
ajp 8009
shutdown 8005
end
end

the JVM has so many bloody options that this may be the more feasible
solution. also w/ the xx_opts, and d_opts I can use simpler options
hash like

node[‘tomcat’][‘xx_opts’] = { ‘ParallelGCThreads’:’’,
’+UseConcMarkSweepGC’:’’, ‘CompileThreshold’ : ‘10000’ }
node[‘tomcat’][‘d_opts’] = { ‘user.timezone’: ‘UTC’, ‘file.encoding’: ‘UTF8’}

would convert to -XX:ParallelGCThreads -XX:+UseConcMarkSweepGC
-XX:CompileThreshold=10000 -Duser.timezone=UTC -Dfile.encoding=UTF8


#2

Hi Bryan,
I’m looking forward to seeing what the new cookbook looks like because I
greatly rely on your good work!

Firstly, would you be able to make the datasource take an array so that we
can have multiples? In my setup, I use Liquibase to automatically upgrade
the database. I use a special, slightly more privileged but not super, user
to actually do that upgrade and thus have two datasources.

As for jvm options, I would suggest surfacing most options with little
translation (option 2 below). There are the very basic knobs to turn (which
you’ve nicely surfaced) like heap size, GC, etc. However, if I want to
twist another knob then I’m going to want to know exactly what I’m doing.
i.e. maybe a page in the docs for Tomcat says use -XXgofaster so I’m going
to want to know I’ve added -XXgofaster without having to read the cookbook.
Having done similar things in JBoss and Websphere AS I definitely prefer to
know what’s going on.

Lastly, what about context settings for JMS, email, etc. While I doubt you
need to write them in right now it would be nice to have a spot in your
model where they’d fit so that somebody can add it later.

Cheers,
Edward

On Sun, Apr 15, 2012 at 6:46 AM, Bryan Berry bryan.berry@gmail.com wrote:

I am rewriting my tomcat lwrp and here is what I have in mind, partly
inspired by Andrea Campi’s work
https://github.com/andreacampi/application_java

tomcat “liferay” do
gc do
min "256m"
max "512m"
max_perm_size "256m"
algorithm "UseConcMarkSweepGC"
end
profiling do # JMX
port "98204"
ssl false
authentication false
end
datasource do
driver 'org.gjt.mm.mysql.Driver’
database 'name’
port 5678
username 'user’
password 'password’
max_active 1
max_idle 2
max_wait 3
end
ports dof
http 8080
https 8443 # defaults to nil and not used
ajp 8009
shutdown 8005
end

end

Commandline JVM options that don’t fit into the above api would have
to be crammed into an attribute like “additional_opts” or
node[‘tomcat’][‘additional_opts’]

the issue I have is whether to group the options to be used by java
virtual machine by function or by category.

Here is a different take on the tomcat lwrp, the uses a ‘jvm’ block
with the xx_opts and d_opts which correspond to -XX, and -D options.
thoughts?

tomcat “pentaho” do
path "/opt/pentaho"
version "7"
user "pentaho"
unpack_wars true
auto_deploy true
environment { }
jvm do
xms "256m"
xmx "512m"
max_perm_size "256m"
xx_opts { }
d_opts { }
additional_opts [ ]
end
datasource do
driver 'org.gjt.mm.mysql.Driver’
database 'name’
port 5678
username 'user’
password 'password’
max_active 1
max_idle 2
max_wait 3
end
ports do
http 8080
https 8443 # defaults to nil and not used
ajp 8009
shutdown 8005
end
end

the JVM has so many bloody options that this may be the more feasible
solution. also w/ the xx_opts, and d_opts I can use simpler options
hash like

node[‘tomcat’][‘xx_opts’] = { ‘ParallelGCThreads’:’’,
’+UseConcMarkSweepGC’:’’, ‘CompileThreshold’ : ‘10000’ }
node[‘tomcat’][‘d_opts’] = { ‘user.timezone’: ‘UTC’, ‘file.encoding’:
‘UTF8’}

would convert to -XX:ParallelGCThreads -XX:+UseConcMarkSweepGC
-XX:CompileThreshold=10000 -Duser.timezone=UTC -Dfile.encoding=UTF8


#3

Hey Edward,

thanks for the encouragement :wink:

it wouldn’t be terribly difficult to add support for multiple
datasources. At first I will only support one and I will try to get to
additional ones when i get the chance. i could add support for passing
an array to context_template

to have multiple i think it would be better to have something like
this than passing an array of hashes to datasource

datasource “foo” do

end

creates tomcat_home/conf/Catalina/localhost/foo.xml

datasource “bar” do

end

creates tomcat_home/conf/Catalina/localhost/bar.xml

you could however easily add an additional datasource by templating an
additional context file in tomcat_home/conf/Catalina/localhost/

for -XXgofaster that would belong under the xx_opts

Of the two apis which I have presented, which do you prefer?

in regards to supporting additional functionality like jms, e-mail etc.

I think that would be best served by something like this

context_template :mix_of_stuff => “your_jms_template.erb”

and that could create tomcat_home/conf/Catalina/localhost/mix_of_stuff.xml

I haven’t yet dealt w/ e-mail and jms settings so will have to think
about how best to handle those w/ an lwrp

thanks for your feedback!

On Sun, Apr 15, 2012 at 4:08 PM, Edward Sargisson esarge@pobox.com wrote:

Hi Bryan,
I’m looking forward to seeing what the new cookbook looks like because I
greatly rely on your good work!

Firstly, would you be able to make the datasource take an array so that we
can have multiples? In my setup, I use Liquibase to automatically upgrade
the database. I use a special, slightly more privileged but not super, user
to actually do that upgrade and thus have two datasources.

As for jvm options, I would suggest surfacing most options with little
translation (option 2 below). There are the very basic knobs to turn (which
you’ve nicely surfaced) like heap size, GC, etc. However, if I want to twist
another knob then I’m going to want to know exactly what I’m doing. i.e.
maybe a page in the docs for Tomcat says use -XXgofaster so I’m going to
want to know I’ve added -XXgofaster without having to read the cookbook.
Having done similar things in JBoss and Websphere AS I definitely prefer to
know what’s going on.

Lastly, what about context settings for JMS, email, etc. While I doubt you
need to write them in right now it would be nice to have a spot in your
model where they’d fit so that somebody can add it later.

Cheers,
Edward

On Sun, Apr 15, 2012 at 6:46 AM, Bryan Berry bryan.berry@gmail.com wrote:

I am rewriting my tomcat lwrp and here is what I have in mind, partly
inspired by Andrea Campi’s work
https://github.com/andreacampi/application_java

tomcat “liferay” do
gc do
min "256m"
max "512m"
max_perm_size "256m"
algorithm "UseConcMarkSweepGC"
end
profiling do # JMX
port "98204"
ssl false
authentication false
end
datasource do
driver 'org.gjt.mm.mysql.Driver’
database 'name’
port 5678
username 'user’
password 'password’
max_active 1
max_idle 2
max_wait 3
end
ports dof
http 8080
https 8443 # defaults to nil and not used
ajp 8009
shutdown 8005
end

end

Commandline JVM options that don’t fit into the above api would have
to be crammed into an attribute like “additional_opts” or
node[‘tomcat’][‘additional_opts’]

the issue I have is whether to group the options to be used by java
virtual machine by function or by category.

Here is a different take on the tomcat lwrp, the uses a ‘jvm’ block
with the xx_opts and d_opts which correspond to -XX, and -D options.
thoughts?

tomcat “pentaho” do
path "/opt/pentaho"
version "7"
user "pentaho"
unpack_wars true
auto_deploy true
environment { }
jvm do
xms "256m"
xmx "512m"
max_perm_size "256m"
xx_opts { }
d_opts { }
additional_opts [ ]
end
datasource do
driver 'org.gjt.mm.mysql.Driver’
database 'name’
port 5678
username 'user’
password 'password’
max_active 1
max_idle 2
max_wait 3
end
ports do
http 8080
https 8443 # defaults to nil and not used
ajp 8009
shutdown 8005
end
end

the JVM has so many bloody options that this may be the more feasible
solution. also w/ the xx_opts, and d_opts I can use simpler options
hash like

node[‘tomcat’][‘xx_opts’] = { ‘ParallelGCThreads’:’’,
’+UseConcMarkSweepGC’:’’, ‘CompileThreshold’ : ‘10000’ }
node[‘tomcat’][‘d_opts’] = { ‘user.timezone’: ‘UTC’, ‘file.encoding’:
‘UTF8’}

would convert to -XX:ParallelGCThreads -XX:+UseConcMarkSweepGC
-XX:CompileThreshold=10000 -Duser.timezone=UTC -Dfile.encoding=UTF8


#4

Hi Bryan,
I fear I’m a little confused. In Tomcat6, my understanding is that you have
to have a single context for each web app. Thus, the two (or more) data
sources have to be included in the same file so your comments about foo.xml
don’t make sense to me. What have I missed?

I prefer the xx_opts method. It’s much clearer what’s happening.

Agree that allowing a context template for complex configs is a nice
solution.

Cheers,
Edward

On Sun, Apr 15, 2012 at 7:21 AM, Bryan Berry bryan.berry@gmail.com wrote:

Hey Edward,

thanks for the encouragement :wink:

it wouldn’t be terribly difficult to add support for multiple
datasources. At first I will only support one and I will try to get to
additional ones when i get the chance. i could add support for passing
an array to context_template

to have multiple i think it would be better to have something like
this than passing an array of hashes to datasource

datasource “foo” do

end

creates tomcat_home/conf/Catalina/localhost/foo.xml

datasource “bar” do

end

creates tomcat_home/conf/Catalina/localhost/bar.xml

you could however easily add an additional datasource by templating an
additional context file in tomcat_home/conf/Catalina/localhost/

for -XXgofaster that would belong under the xx_opts

Of the two apis which I have presented, which do you prefer?

in regards to supporting additional functionality like jms, e-mail etc.

I think that would be best served by something like this

context_template :mix_of_stuff => “your_jms_template.erb”

and that could create tomcat_home/conf/Catalina/localhost/mix_of_stuff.xml

I haven’t yet dealt w/ e-mail and jms settings so will have to think
about how best to handle those w/ an lwrp

thanks for your feedback!

On Sun, Apr 15, 2012 at 4:08 PM, Edward Sargisson esarge@pobox.com
wrote:

Hi Bryan,
I’m looking forward to seeing what the new cookbook looks like because I
greatly rely on your good work!

Firstly, would you be able to make the datasource take an array so that
we
can have multiples? In my setup, I use Liquibase to automatically upgrade
the database. I use a special, slightly more privileged but not super,
user
to actually do that upgrade and thus have two datasources.

As for jvm options, I would suggest surfacing most options with little
translation (option 2 below). There are the very basic knobs to turn
(which
you’ve nicely surfaced) like heap size, GC, etc. However, if I want to
twist
another knob then I’m going to want to know exactly what I’m doing. i.e.
maybe a page in the docs for Tomcat says use -XXgofaster so I’m going to
want to know I’ve added -XXgofaster without having to read the cookbook.
Having done similar things in JBoss and Websphere AS I definitely prefer
to
know what’s going on.

Lastly, what about context settings for JMS, email, etc. While I doubt
you
need to write them in right now it would be nice to have a spot in your
model where they’d fit so that somebody can add it later.

Cheers,
Edward

On Sun, Apr 15, 2012 at 6:46 AM, Bryan Berry bryan.berry@gmail.com
wrote:

I am rewriting my tomcat lwrp and here is what I have in mind, partly
inspired by Andrea Campi’s work
https://github.com/andreacampi/application_java

tomcat “liferay” do
gc do
min "256m"
max "512m"
max_perm_size "256m"
algorithm "UseConcMarkSweepGC"
end
profiling do # JMX
port "98204"
ssl false
authentication false
end
datasource do
driver 'org.gjt.mm.mysql.Driver’
database 'name’
port 5678
username 'user’
password 'password’
max_active 1
max_idle 2
max_wait 3
end
ports dof
http 8080
https 8443 # defaults to nil and not used
ajp 8009
shutdown 8005
end

end

Commandline JVM options that don’t fit into the above api would have
to be crammed into an attribute like “additional_opts” or
node[‘tomcat’][‘additional_opts’]

the issue I have is whether to group the options to be used by java
virtual machine by function or by category.

Here is a different take on the tomcat lwrp, the uses a ‘jvm’ block
with the xx_opts and d_opts which correspond to -XX, and -D options.
thoughts?

tomcat “pentaho” do
path "/opt/pentaho"
version "7"
user "pentaho"
unpack_wars true
auto_deploy true
environment { }
jvm do
xms "256m"
xmx "512m"
max_perm_size "256m"
xx_opts { }
d_opts { }
additional_opts [ ]
end
datasource do
driver 'org.gjt.mm.mysql.Driver’
database 'name’
port 5678
username 'user’
password 'password’
max_active 1
max_idle 2
max_wait 3
end
ports do
http 8080
https 8443 # defaults to nil and not used
ajp 8009
shutdown 8005
end
end

the JVM has so many bloody options that this may be the more feasible
solution. also w/ the xx_opts, and d_opts I can use simpler options
hash like

node[‘tomcat’][‘xx_opts’] = { ‘ParallelGCThreads’:’’,
’+UseConcMarkSweepGC’:’’, ‘CompileThreshold’ : ‘10000’ }
node[‘tomcat’][‘d_opts’] = { ‘user.timezone’: ‘UTC’, ‘file.encoding’:
‘UTF8’}

would convert to -XX:ParallelGCThreads -XX:+UseConcMarkSweepGC
-XX:CompileThreshold=10000 -Duser.timezone=UTC -Dfile.encoding=UTF8


#5

Hey Edward,

I was mistaken, you can only have one Context element thus only 1
TOMCAT_HOME/conf/Catalina/localhost/foo.xml

I would have to aggregate the datasources into a single context file

I have a few more questions if you don’t mind

Which would you prefer?

d_opts OR directives ?

additional_opts OR extra_opts OR additional_properties OR
even_more_crap ?

tks for your feedback!

On Mon, Apr 16, 2012 at 6:00 AM, Edward Sargisson esarge@pobox.com wrote:

Hi Bryan,
I fear I’m a little confused. In Tomcat6, my understanding is that you
have to have a single context for each web app. Thus, the two (or more)
data sources have to be included in the same file so your comments about
foo.xml don’t make sense to me. What have I missed?

I prefer the xx_opts method. It’s much clearer what’s happening.

Agree that allowing a context template for complex configs is a nice
solution.

Cheers,
Edward

On Sun, Apr 15, 2012 at 7:21 AM, Bryan Berry bryan.berry@gmail.comwrote:

Hey Edward,

thanks for the encouragement :wink:

it wouldn’t be terribly difficult to add support for multiple
datasources. At first I will only support one and I will try to get to
additional ones when i get the chance. i could add support for passing
an array to context_template

to have multiple i think it would be better to have something like
this than passing an array of hashes to datasource

datasource “foo” do

end

creates tomcat_home/conf/Catalina/localhost/foo.xml

datasource “bar” do

end

creates tomcat_home/conf/Catalina/localhost/bar.xml

you could however easily add an additional datasource by templating an
additional context file in tomcat_home/conf/Catalina/localhost/

for -XXgofaster that would belong under the xx_opts

Of the two apis which I have presented, which do you prefer?

in regards to supporting additional functionality like jms, e-mail etc.

I think that would be best served by something like this

context_template :mix_of_stuff => “your_jms_template.erb”

and that could create tomcat_home/conf/Catalina/localhost/mix_of_stuff.xml

I haven’t yet dealt w/ e-mail and jms settings so will have to think
about how best to handle those w/ an lwrp

thanks for your feedback!

On Sun, Apr 15, 2012 at 4:08 PM, Edward Sargisson esarge@pobox.com
wrote:

Hi Bryan,
I’m looking forward to seeing what the new cookbook looks like because I
greatly rely on your good work!

Firstly, would you be able to make the datasource take an array so that
we
can have multiples? In my setup, I use Liquibase to automatically
upgrade
the database. I use a special, slightly more privileged but not super,
user
to actually do that upgrade and thus have two datasources.

As for jvm options, I would suggest surfacing most options with little
translation (option 2 below). There are the very basic knobs to turn
(which
you’ve nicely surfaced) like heap size, GC, etc. However, if I want to
twist
another knob then I’m going to want to know exactly what I’m doing. i.e.
maybe a page in the docs for Tomcat says use -XXgofaster so I’m going to
want to know I’ve added -XXgofaster without having to read the cookbook.
Having done similar things in JBoss and Websphere AS I definitely
prefer to
know what’s going on.

Lastly, what about context settings for JMS, email, etc. While I doubt
you
need to write them in right now it would be nice to have a spot in your
model where they’d fit so that somebody can add it later.

Cheers,
Edward

On Sun, Apr 15, 2012 at 6:46 AM, Bryan Berry bryan.berry@gmail.com
wrote:

I am rewriting my tomcat lwrp and here is what I have in mind, partly
inspired by Andrea Campi’s work
https://github.com/andreacampi/application_java

tomcat “liferay” do
gc do
min "256m"
max "512m"
max_perm_size "256m"
algorithm "UseConcMarkSweepGC"
end
profiling do # JMX
port "98204"
ssl false
authentication false
end
datasource do
driver 'org.gjt.mm.mysql.Driver’
database 'name’
port 5678
username 'user’
password 'password’
max_active 1
max_idle 2
max_wait 3
end
ports dof
http 8080
https 8443 # defaults to nil and not used
ajp 8009
shutdown 8005
end

end

Commandline JVM options that don’t fit into the above api would have
to be crammed into an attribute like “additional_opts” or
node[‘tomcat’][‘additional_opts’]

the issue I have is whether to group the options to be used by java
virtual machine by function or by category.

Here is a different take on the tomcat lwrp, the uses a ‘jvm’ block
with the xx_opts and d_opts which correspond to -XX, and -D options.
thoughts?

tomcat “pentaho” do
path "/opt/pentaho"
version "7"
user "pentaho"
unpack_wars true
auto_deploy true
environment { }
jvm do
xms "256m"
xmx "512m"
max_perm_size "256m"
xx_opts { }
d_opts { }
additional_opts [ ]
end
datasource do
driver 'org.gjt.mm.mysql.Driver’
database 'name’
port 5678
username 'user’
password 'password’
max_active 1
max_idle 2
max_wait 3
end
ports do
http 8080
https 8443 # defaults to nil and not used
ajp 8009
shutdown 8005
end
end

the JVM has so many bloody options that this may be the more feasible
solution. also w/ the xx_opts, and d_opts I can use simpler options
hash like

node[‘tomcat’][‘xx_opts’] = { ‘ParallelGCThreads’:’’,
’+UseConcMarkSweepGC’:’’, ‘CompileThreshold’ : ‘10000’ }
node[‘tomcat’][‘d_opts’] = { ‘user.timezone’: ‘UTC’, ‘file.encoding’:
‘UTF8’}

would convert to -XX:ParallelGCThreads -XX:+UseConcMarkSweepGC
-XX:CompileThreshold=10000 -Duser.timezone=UTC -Dfile.encoding=UTF8


#6

E Sarge,

just as importantly, would you find the following confusing?

http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html

I want to represent the -XX:* options like this

jvm do
xx_opts do
use_conc_mark_sweep_gc true # becomes -XX:+UseConcMarkSweepGC
on command line
allow_user_signal_handlers false # becomes -XX:
-AllowUserSignalHandlers
max_heap_free_ratio 70 # becomes -XX:
MaxHeapFreeRatio=70
end
end

What do you think? does it just make things more complex or does it make it
more readable?

On Mon, Apr 16, 2012 at 7:17 AM, Bryan Berry bryan.berry@gmail.com wrote:

Hey Edward,

I was mistaken, you can only have one Context element thus only 1
TOMCAT_HOME/conf/Catalina/localhost/foo.xml

I would have to aggregate the datasources into a single context file

I have a few more questions if you don’t mind

Which would you prefer?

d_opts OR directives ?

additional_opts OR extra_opts OR additional_properties OR
even_more_crap ?

tks for your feedback!

On Mon, Apr 16, 2012 at 6:00 AM, Edward Sargisson esarge@pobox.comwrote:

Hi Bryan,
I fear I’m a little confused. In Tomcat6, my understanding is that you
have to have a single context for each web app. Thus, the two (or more)
data sources have to be included in the same file so your comments about
foo.xml don’t make sense to me. What have I missed?

I prefer the xx_opts method. It’s much clearer what’s happening.

Agree that allowing a context template for complex configs is a nice
solution.

Cheers,
Edward

On Sun, Apr 15, 2012 at 7:21 AM, Bryan Berry bryan.berry@gmail.comwrote:

Hey Edward,

thanks for the encouragement :wink:

it wouldn’t be terribly difficult to add support for multiple
datasources. At first I will only support one and I will try to get to
additional ones when i get the chance. i could add support for passing
an array to context_template

to have multiple i think it would be better to have something like
this than passing an array of hashes to datasource

datasource “foo” do

end

creates tomcat_home/conf/Catalina/localhost/foo.xml

datasource “bar” do

end

creates tomcat_home/conf/Catalina/localhost/bar.xml

you could however easily add an additional datasource by templating an
additional context file in tomcat_home/conf/Catalina/localhost/

for -XXgofaster that would belong under the xx_opts

Of the two apis which I have presented, which do you prefer?

in regards to supporting additional functionality like jms, e-mail etc.

I think that would be best served by something like this

context_template :mix_of_stuff => “your_jms_template.erb”

and that could create
tomcat_home/conf/Catalina/localhost/mix_of_stuff.xml

I haven’t yet dealt w/ e-mail and jms settings so will have to think
about how best to handle those w/ an lwrp

thanks for your feedback!

On Sun, Apr 15, 2012 at 4:08 PM, Edward Sargisson esarge@pobox.com
wrote:

Hi Bryan,
I’m looking forward to seeing what the new cookbook looks like because
I
greatly rely on your good work!

Firstly, would you be able to make the datasource take an array so
that we
can have multiples? In my setup, I use Liquibase to automatically
upgrade
the database. I use a special, slightly more privileged but not super,
user
to actually do that upgrade and thus have two datasources.

As for jvm options, I would suggest surfacing most options with little
translation (option 2 below). There are the very basic knobs to turn
(which
you’ve nicely surfaced) like heap size, GC, etc. However, if I want to
twist
another knob then I’m going to want to know exactly what I’m doing.
i.e.
maybe a page in the docs for Tomcat says use -XXgofaster so I’m going
to
want to know I’ve added -XXgofaster without having to read the
cookbook.
Having done similar things in JBoss and Websphere AS I definitely
prefer to
know what’s going on.

Lastly, what about context settings for JMS, email, etc. While I doubt
you
need to write them in right now it would be nice to have a spot in your
model where they’d fit so that somebody can add it later.

Cheers,
Edward

On Sun, Apr 15, 2012 at 6:46 AM, Bryan Berry bryan.berry@gmail.com
wrote:

I am rewriting my tomcat lwrp and here is what I have in mind, partly
inspired by Andrea Campi’s work
https://github.com/andreacampi/application_java

tomcat “liferay” do
gc do
min "256m"
max "512m"
max_perm_size "256m"
algorithm "UseConcMarkSweepGC"
end
profiling do # JMX
port "98204"
ssl false
authentication false
end
datasource do
driver 'org.gjt.mm.mysql.Driver’
database 'name’
port 5678
username 'user’
password 'password’
max_active 1
max_idle 2
max_wait 3
end
ports dof
http 8080
https 8443 # defaults to nil and not used
ajp 8009
shutdown 8005
end

end

Commandline JVM options that don’t fit into the above api would have
to be crammed into an attribute like “additional_opts” or
node[‘tomcat’][‘additional_opts’]

the issue I have is whether to group the options to be used by java
virtual machine by function or by category.

Here is a different take on the tomcat lwrp, the uses a ‘jvm’ block
with the xx_opts and d_opts which correspond to -XX, and -D options.
thoughts?

tomcat “pentaho” do
path "/opt/pentaho"
version "7"
user "pentaho"
unpack_wars true
auto_deploy true
environment { }
jvm do
xms "256m"
xmx "512m"
max_perm_size "256m"
xx_opts { }
d_opts { }
additional_opts [ ]
end
datasource do
driver 'org.gjt.mm.mysql.Driver’
database 'name’
port 5678
username 'user’
password 'password’
max_active 1
max_idle 2
max_wait 3
end
ports do
http 8080
https 8443 # defaults to nil and not used
ajp 8009
shutdown 8005
end
end

the JVM has so many bloody options that this may be the more feasible
solution. also w/ the xx_opts, and d_opts I can use simpler options
hash like

node[‘tomcat’][‘xx_opts’] = { ‘ParallelGCThreads’:’’,
’+UseConcMarkSweepGC’:’’, ‘CompileThreshold’ : ‘10000’ }
node[‘tomcat’][‘d_opts’] = { ‘user.timezone’: ‘UTC’, ‘file.encoding’:
‘UTF8’}

would convert to -XX:ParallelGCThreads -XX:+UseConcMarkSweepGC
-XX:CompileThreshold=10000 -Duser.timezone=UTC -Dfile.encoding=UTF8


#7

Hi Bryan and all,

On Sun, Apr 15, 2012 at 3:46 PM, Bryan Berry bryan.berry@gmail.com wrote:

I am rewriting my tomcat lwrp and here is what I have in mind, partly
inspired by Andrea Campi’s work
https://github.com/andreacampi/application_java

first of all, thanks for the pointer but it was Noah who came up with
the DSL; I’m “just” finish up what he started and shepherding it into
the repo.

I haven’t had time to work on Java apps since we talked, but I do have
some opinions.

First of all, I like what you’re doing but I think it doesn’t belong
in the Tomcat cookbook.
Looking at your examples, I would say every option except perhaps the
ports would make sense for a standalone non-web-app.
And what about running on JBoss or Jetty? What about JRuby or Scala apps?

The goal of the application cookbook is to abstract away commonalities
and provide a single language to as many frameworks as reasonable,
while still allowing specific configuration.

Without getting too specific, my main point here is: let’s join effort
and make sure we don’t invent almost the same thing twice.

Concerning multiple database connections:
that’s something I thought about for Rails and other frameworks. I
looked back at enhancement requests tickets and while there have been
requests to support apps with no SQL database, I couldn’t find any
requesting more than one.
In the end I decided not to add any special logic, and put in an
option to specify a custom template (akin to your context_template).

When I doubt I go with the 80/20 rule: 80% or more people will be
covered by the logic for one DB connection; 80% of the remaining will
be able to get by with a custom template; the remaining setups will
probably have very specific needs anyway, and may as well implement
their custom logic by editing the cookbook.

To answer your questions:

tomcat “pentaho” do

jvm do
xms "256m"
xmx "512m"
max_perm_size "256m"
xx_opts { }
d_opts { }
additional_opts [ ]
end
end

the JVM has so many bloody options that this may be the more feasible
solution. also w/ the xx_opts, and d_opts I can use simpler options
hash like

node[‘tomcat’][‘xx_opts’] = { ‘ParallelGCThreads’:’’,
’+UseConcMarkSweepGC’:’’, ‘CompileThreshold’ : ‘10000’ }
node[‘tomcat’][‘d_opts’] = { ‘user.timezone’: ‘UTC’, ‘file.encoding’: ‘UTF8’}

would convert to -XX:ParallelGCThreads -XX:+UseConcMarkSweepGC
-XX:CompileThreshold=10000 -Duser.timezone=UTC -Dfile.encoding=UTF8

I’d rather go this way for a simple reason: many of these settings are
not really per-app, they are more per-site or per-node.
A nice DSL is very convenient, but for stuff like file.encoding I just
want to set it on a role and be done with it.

Ditto for your last example:

jvm do
xx_opts do
use_conc_mark_sweep_gc true # becomes -XX:+UseConcMarkSweepGC on command line
allow_user_signal_handlers false # becomes -XX:-AllowUserSignalHandlers
max_heap_free_ratio 70 # becomes -XX:MaxHeapFreeRatio=70
end
end

I want to be able to grep for UseConcMarkSweepGC anywhere; remembering
that I have to spell that as use_conc_mark_sweep_gc just here is extra
mental burden I frankly don’t need :slight_smile:

Hope this helps. I’ll find you online tonight and we can talk more?

Andrea


#8

Hey Andrea

First of all, I like what you’re doing but I think it doesn’t belong
in the Tomcat cookbook.
Looking at your examples, I would say every option except perhaps the
ports would make sense for a standalone non-web-app.
And what about running on JBoss or Jetty? What about JRuby or Scala apps?

It may best belong in the java cookbook at java/libraries/java_webapp.rb .
It definitely applies in some aspect to jboss, jetty, jruby, scala, etc.

I am very happy to join forces at the same time I do have to write
something that 100% solves my problems at work otherwise I will go insane
over the next couple months ;).

node[‘tomcat’][‘xx_opts’] = { ‘ParallelGCThreads’:’’,
’+UseConcMarkSweepGC’:’’, ‘CompileThreshold’ : ‘10000’ }
node[‘tomcat’][‘d_opts’] = { ‘user.timezone’: ‘UTC’, ‘file.encoding’:
‘UTF8’}

would convert to -XX:ParallelGCThreads -XX:+UseConcMarkSweepGC
-XX:CompileThreshold=10000 -Duser.timezone=UTC -Dfile.encoding=UTF8

would this work for you?

xx_opts ‘UseParallelGC’ => true, ‘UseConcMarkSweepGC’ => true,
‘CompileThreshold’
=> 10000

Which would convert to -XX:+UseParallelGC -XX:+UseConcMarkSweepGC
-XX:CompileThreshold=10000

so the boolean values convert to ‘+’ prefixes otherwise the value will be
’=’ something

while the jvm and ports helpers map easily to tomcat, jetty, jboss, etc,
the datasources may not

also, I suggest we call the attribute ‘datasource’ and not ‘database’ as
that is more common in the java docs. However you may use the database name
elsewhere in the application cookbook

cheers

On Mon, Apr 16, 2012 at 8:35 AM, Andrea Campi
andrea.campi@zephirworks.comwrote:

Hi Bryan and all,

On Sun, Apr 15, 2012 at 3:46 PM, Bryan Berry bryan.berry@gmail.com
wrote:

I am rewriting my tomcat lwrp and here is what I have in mind, partly
inspired by Andrea Campi’s work
https://github.com/andreacampi/application_java

first of all, thanks for the pointer but it was Noah who came up with
the DSL; I’m “just” finish up what he started and shepherding it into
the repo.

I haven’t had time to work on Java apps since we talked, but I do have
some opinions.

First of all, I like what you’re doing but I think it doesn’t belong
in the Tomcat cookbook.
Looking at your examples, I would say every option except perhaps the
ports would make sense for a standalone non-web-app.
And what about running on JBoss or Jetty? What about JRuby or Scala apps?

The goal of the application cookbook is to abstract away commonalities
and provide a single language to as many frameworks as reasonable,
while still allowing specific configuration.

Without getting too specific, my main point here is: let’s join effort
and make sure we don’t invent almost the same thing twice.

Concerning multiple database connections:
that’s something I thought about for Rails and other frameworks. I
looked back at enhancement requests tickets and while there have been
requests to support apps with no SQL database, I couldn’t find any
requesting more than one.
In the end I decided not to add any special logic, and put in an
option to specify a custom template (akin to your context_template).

When I doubt I go with the 80/20 rule: 80% or more people will be
covered by the logic for one DB connection; 80% of the remaining will
be able to get by with a custom template; the remaining setups will
probably have very specific needs anyway, and may as well implement
their custom logic by editing the cookbook.

To answer your questions:

tomcat “pentaho” do

jvm do
xms "256m"
xmx "512m"
max_perm_size "256m"
xx_opts { }
d_opts { }
additional_opts [ ]
end
end

the JVM has so many bloody options that this may be the more feasible
solution. also w/ the xx_opts, and d_opts I can use simpler options
hash like

node[‘tomcat’][‘xx_opts’] = { ‘ParallelGCThreads’:’’,
’+UseConcMarkSweepGC’:’’, ‘CompileThreshold’ : ‘10000’ }
node[‘tomcat’][‘d_opts’] = { ‘user.timezone’: ‘UTC’, ‘file.encoding’:
‘UTF8’}

would convert to -XX:ParallelGCThreads -XX:+UseConcMarkSweepGC
-XX:CompileThreshold=10000 -Duser.timezone=UTC -Dfile.encoding=UTF8

I’d rather go this way for a simple reason: many of these settings are
not really per-app, they are more per-site or per-node.
A nice DSL is very convenient, but for stuff like file.encoding I just
want to set it on a role and be done with it.

Ditto for your last example:

jvm do
xx_opts do
use_conc_mark_sweep_gc true # becomes
-XX:+UseConcMarkSweepGC on command line
allow_user_signal_handlers false # becomes
-XX:-AllowUserSignalHandlers
max_heap_free_ratio 70 # becomes
-XX:MaxHeapFreeRatio=70
end
end

I want to be able to grep for UseConcMarkSweepGC anywhere; remembering
that I have to spell that as use_conc_mark_sweep_gc just here is extra
mental burden I frankly don’t need :slight_smile:

Hope this helps. I’ll find you online tonight and we can talk more?

Andrea


#9

Hi,

On Mon, Apr 16, 2012 at 4:35 PM, Andrea Campi
andrea.campi@zephirworks.com wrote:

First of all, I like what you’re doing but I think it doesn’t belong
in the Tomcat cookbook.
Looking at your examples, I would say every option except perhaps the
ports would make sense for a standalone non-web-app.
And what about running on JBoss or Jetty? What about JRuby or Scala apps?

The goal of the application cookbook is to abstract away commonalities
and provide a single language to as many frameworks as reasonable,
while still allowing specific configuration.

Without getting too specific, my main point here is: let’s join effort
and make sure we don’t invent almost the same thing twice.

I would be interested in this. Currently in my setup we actually have
common bits of code that I use to set up jmx across all the jvms. i.e.
Our users databag gives credentials for jmx and then we can use this
combined with app specific groups to generated access control files
and password files for jmx access. We have also a common bit of code
that we use to setup all the jdk logging options across our jvms.
(Mostly so we can ship stuff over to a graylog server)


Cheers,

Peter Donald


#10

Hey Peter,

can you point me to the code you use for configuring your jmx access?
Of the top of my head this would be best served by an heavyweight
resource provider (HWRP? PORO?) and some helper functions, both of
which could live in the in the java cookbook

Actually depositing user credentials into the credentials file for the
jvm could be a helper function that you invoke from your users recipe

What kind of resource would you like to see for the jdk logging and
jmx configuration?

Do you prefer the layout of what i have in the following example or w/
the more explicit xx_opts, d_opts, additional_opts attributes?

jvm do
xms '256m’
xmx '512m’
jmx do
auth
ssl
end
logging do

end
end

If you myself and Andrea could find the time to chat I think it would
be very beneficial to all of us.

I am on irc from 07:00 - 18:00 CET most days and will be coding this
weekend on the tomcat cookbook. Both Andrea and I are on CET. Peter, u
r in Australia?

On Tue, Apr 17, 2012 at 3:14 AM, Peter Donald peter@realityforge.org wrote:

Hi,

On Mon, Apr 16, 2012 at 4:35 PM, Andrea Campi
andrea.campi@zephirworks.com wrote:

First of all, I like what you’re doing but I think it doesn’t belong
in the Tomcat cookbook.
Looking at your examples, I would say every option except perhaps the
ports would make sense for a standalone non-web-app.
And what about running on JBoss or Jetty? What about JRuby or Scala apps?

The goal of the application cookbook is to abstract away commonalities
and provide a single language to as many frameworks as reasonable,
while still allowing specific configuration.

Without getting too specific, my main point here is: let’s join effort
and make sure we don’t invent almost the same thing twice.

I would be interested in this. Currently in my setup we actually have
common bits of code that I use to set up jmx across all the jvms. i.e.
Our users databag gives credentials for jmx and then we can use this
combined with app specific groups to generated access control files
and password files for jmx access. We have also a common bit of code
that we use to setup all the jdk logging options across our jvms.
(Mostly so we can ship stuff over to a graylog server)


Cheers,

Peter Donald


#11

Hi,

On Tue, Apr 17, 2012 at 3:52 PM, Bryan Berry bryan.berry@gmail.com wrote:

can you point me to the code you use for configuring your jmx access?
Of the top of my head this would be best served by an heavyweight
resource provider (HWRP? PORO?) and some helper functions, both of
which could live in the in the java cookbook

I don’t have the extracted version handy but you can see an older
variant of the functionality in

https://github.com/realityforge-cookbooks/glassfish/blob/master/providers/mq.rb

the relevant parts being


if new_resource.jmx_port
vm_args << "-Dcom.sun.management.jmxremote"
vm_args << "-Dcom.sun.management.jmxremote.port=#{new_resource.jmx_port}"
vm_args << "-Dcom.sun.management.jmxremote.access.file=#{instance_dir}/etc/jmxremote.access"
vm_args << "-Dcom.sun.management.jmxremote.password.file=#{instance_dir}/etc/jmxremote.password"
vm_args << "-Dcom.sun.management.jmxremote.ssl=false"
end

if new_resource.jmx_port && new_resource.jmx_port < 1024
authbind_port “AuthBind GlassFish OpenMQ JMX Port
#{new_resource.jmx_port}” do
port new_resource.jmx_port
user node[:glassfish][:user]
end
end

if new_resource.jmx_port
admins = {}
search(:users, “groups:#{new_resource.admin_group} AND
jmx_password:") do |u|
admins[u[‘id’]] = u[‘jmx_password’]
end
monitors = {}
search(:users, "groups:#{new_resource.monitor_group} AND
jmx_password:
”) do |u|
monitors[u[‘id’]] = u[‘jmx_password’]
end

file "#{instance_dir}/etc/jmxremote.access" do
  owner node[:glassfish][:user]
  group node[:glassfish][:group]
  mode "0400"
  action :create
  content (admins.keys.sort.collect { |username|

“#{username}=readwrite\n” } + monitors.keys.sort.collect { |username|
"#{username}=readonly\n" }).join("")
notifies :restart, resources(:service =>
“omq-#{new_resource.instance}”), :delayed
end

file "#{instance_dir}/etc/jmxremote.password" do
  owner node[:glassfish][:user]
  group node[:glassfish][:group]
  mode "0400"
  action :create
  content (admins.sort.collect { |username, password|

“#{username}=#{password}\n” } + monitors.sort.collect { |username,
password| “#{username}=#{password}\n” }).join("")
notifies :restart, resources(:service =>
“omq-#{new_resource.instance}”), :delayed
end
end


For jdk logging I also have some similar code but none in a public
space atm. But mostly it is about merging multiple property files if
any values are not set. This essentially allows me to send all the
logs to a central syslog style server (ie graylog)

What kind of resource would you like to see for the jdk logging and
jmx configuration?

Do you prefer the layout of what i have in the following example or w/
the more explicit xx_opts, d_opts, additional_opts attributes?

jvm do
xms '256m’
xmx '512m’
jmx do
auth
ssl
end
logging do

end
end

ultimately I am not entirely sure. The approach I currently use is to
separate the cookbook into 4 components;

  • a recipe for the baseline binary install
  • resources/providers for all the relevant resources
  • a description of the application either in either node properties or
    as a databag item
  • a recipe that reads the description and invokes the relevant resource

Here’s a sample of what I use

override[:glassfish][:domain_definitions][:planner] =
{
:config =>
{
:max_memory => 1548,
:max_perm_size => 192,
:port => 80,
:admin_port => 8082,
:username => ‘…’,
:password => ‘…’
},
:extra_libraries =>
[
‘http://…/content/repositories/releases/net/sourceforge/jtds/jtds/1.2.5/jtds-1.2.5.jar’
],
:jvm_options => ["-Djava.naming.referral=follow"], #Required for
ActiveDirectory
:sets =>
[
“configs.config.server-config.security-service.activate-default-principal-to-role-mapping=true”,
“configs.config.server-config.security-service.default-realm=ldapRealm”
],
:realms =>
{
:ldapRealm =>
{
:parameters =>
[
"–classname
com.sun.enterprise.security.auth.realm.ldap.LDAPRealm",
"–property “…”,
]
}
},
:jdbc_connection_pools =>
{
:firesql =>
{
:parameters =>
[
"–datasourceclassname
net.sourceforge.jtds.jdbcx.JtdsDataSource",
"–restype javax.sql.DataSource",
"–isconnectvalidatereq=true",
"–validationmethod auto-commit",
"–ping true",
"–description “My Connection Pool”",
"–property “…”",
],
:resources =>
{
“jdbc/firesql” =>
{
:parameters => ["–description “My Connection Resource”"]
}
}
}
},
:custom_resources =>
{
“SpecificTaskCreatorServiceURL” =>
“http://…/SpecificTaskCreatorService”
},
:deployables =>
{
:planner =>
{
:version => “0.1”,
:url => “http://…/myapp.war”,
:context_root => “/”
}
}
}

It seems I have a combination of “semantic” (i.e. :max_memory => 1548)
as well as “physical” (i.e. “-Djava.naming.referral=follow”)
configuration. In hindsight I only ever need semantic ones where the
configuration interacts with other parts of the system. i.e :port =>
80 is important as I need to set up authbind rules for it as well as
firewall rules. It is also interrogated by other systems when they are
setting up their firewalls or creating connections to their particular
web services. All the rest of it I prefer to go straight to the raw
underlying configuration rather than trying to have an abstraction
layer (that may be leaky) on the underlying tool.

If you myself and Andrea could find the time to chat I think it would
be very beneficial to all of us.

I am on irc from 07:00 - 18:00 CET most days and will be coding this
weekend on the tomcat cookbook. Both Andrea and I are on CET. Peter, u
r in Australia?

I am in Australia but currently I have next to no net due to moving
house ;( Though hopefully in the next month I can look at some of this
away from my work desk.


Cheers,

Peter Donald


#12

So maybe there’s an idea of a “jee_container” cookbook to represent Tomcat,
JBoss, WAS, Jetty, etc.

The setup would go something like:
application (WAR location, datasources, JMS, mail, etc. Results in the WAR
being download and deployed, a context.xml written and external properties
file and log properties file written into place from template)
jee_container (has a LWRP/recipe for each supported container, JVM
settings, JMX settings, etc)

Should it be called container, java_container, java_ee_container? Oracle
seems to be using the term Java EE.

Cheers,
Edward

On Sun, Apr 15, 2012 at 11:35 PM, Andrea Campi <andrea.campi@zephirworks.com

wrote:

Hi Bryan and all,

On Sun, Apr 15, 2012 at 3:46 PM, Bryan Berry bryan.berry@gmail.com
wrote:

I am rewriting my tomcat lwrp and here is what I have in mind, partly
inspired by Andrea Campi’s work
https://github.com/andreacampi/application_java

first of all, thanks for the pointer but it was Noah who came up with
the DSL; I’m “just” finish up what he started and shepherding it into
the repo.

I haven’t had time to work on Java apps since we talked, but I do have
some opinions.

First of all, I like what you’re doing but I think it doesn’t belong
in the Tomcat cookbook.
Looking at your examples, I would say every option except perhaps the
ports would make sense for a standalone non-web-app.
And what about running on JBoss or Jetty? What about JRuby or Scala apps?

The goal of the application cookbook is to abstract away commonalities
and provide a single language to as many frameworks as reasonable,
while still allowing specific configuration.

Without getting too specific, my main point here is: let’s join effort
and make sure we don’t invent almost the same thing twice.

Concerning multiple database connections:
that’s something I thought about for Rails and other frameworks. I
looked back at enhancement requests tickets and while there have been
requests to support apps with no SQL database, I couldn’t find any
requesting more than one.
In the end I decided not to add any special logic, and put in an
option to specify a custom template (akin to your context_template).

When I doubt I go with the 80/20 rule: 80% or more people will be
covered by the logic for one DB connection; 80% of the remaining will
be able to get by with a custom template; the remaining setups will
probably have very specific needs anyway, and may as well implement
their custom logic by editing the cookbook.

To answer your questions:

tomcat “pentaho” do

jvm do
xms "256m"
xmx "512m"
max_perm_size "256m"
xx_opts { }
d_opts { }
additional_opts [ ]
end
end

the JVM has so many bloody options that this may be the more feasible
solution. also w/ the xx_opts, and d_opts I can use simpler options
hash like

node[‘tomcat’][‘xx_opts’] = { ‘ParallelGCThreads’:’’,
’+UseConcMarkSweepGC’:’’, ‘CompileThreshold’ : ‘10000’ }
node[‘tomcat’][‘d_opts’] = { ‘user.timezone’: ‘UTC’, ‘file.encoding’:
‘UTF8’}

would convert to -XX:ParallelGCThreads -XX:+UseConcMarkSweepGC
-XX:CompileThreshold=10000 -Duser.timezone=UTC -Dfile.encoding=UTF8

I’d rather go this way for a simple reason: many of these settings are
not really per-app, they are more per-site or per-node.
A nice DSL is very convenient, but for stuff like file.encoding I just
want to set it on a role and be done with it.

Ditto for your last example:

jvm do
xx_opts do
use_conc_mark_sweep_gc true # becomes
-XX:+UseConcMarkSweepGC on command line
allow_user_signal_handlers false # becomes
-XX:-AllowUserSignalHandlers
max_heap_free_ratio 70 # becomes
-XX:MaxHeapFreeRatio=70
end
end

I want to be able to grep for UseConcMarkSweepGC anywhere; remembering
that I have to spell that as use_conc_mark_sweep_gc just here is extra
mental burden I frankly don’t need :slight_smile:

Hope this helps. I’ll find you online tonight and we can talk more?

Andrea


#13

On Tue, Apr 17, 2012 at 2:59 PM, Edward Sargisson esarge@pobox.com wrote:

So maybe there’s an idea of a “jee_container” cookbook to represent Tomcat,
JBoss, WAS, Jetty, etc.

The setup would go something like:
application (WAR location, datasources, JMS, mail, etc. Results in the WAR
being download and deployed, a context.xml written and external properties
file and log properties file written into place from template)
jee_container (has a LWRP/recipe for each supported container, JVM settings,
JMX settings, etc)

Not sure a jee_container cookbook is needed, but indeed the java
cookbook could come with an “abstract” LWRP that the “concrete” LWRPs
(Tomcat and so on) could inherit from / mix in.
This would prevent an endless duplication of pretty much the same
stuff all over the place.

Frankly, it looks to me that trying to design a complete solution for
everything would be really hard and time-consuming. I’d rather work
in “agile” way and start with just a couple of stacks; then factor out
commonalities and build from there.
Tomcat is the prime candidate since that’s what the "legacy"
application cookbook had; Glassfish may as well be a second example.

Andrea


#14

i agree w/ Andrea that we should start w/ a simpler JVM base class or
module that can be extended or mixed in

something like Chef::Resource::Jvm

I think creating a generic jee_container will be too much to bite off

I maintain both tomcat and jboss cookbooks and I don’t think I could
make a jee_container class that could accommodate both.

On Tue, Apr 17, 2012 at 3:17 PM, Andrea Campi
andrea.campi@zephirworks.com wrote:

On Tue, Apr 17, 2012 at 2:59 PM, Edward Sargisson esarge@pobox.com wrote:

So maybe there’s an idea of a “jee_container” cookbook to represent Tomcat,
JBoss, WAS, Jetty, etc.

The setup would go something like:
application (WAR location, datasources, JMS, mail, etc. Results in the WAR
being download and deployed, a context.xml written and external properties
file and log properties file written into place from template)
jee_container (has a LWRP/recipe for each supported container, JVM settings,
JMX settings, etc)

Not sure a jee_container cookbook is needed, but indeed the java
cookbook could come with an “abstract” LWRP that the “concrete” LWRPs
(Tomcat and so on) could inherit from / mix in.
This would prevent an endless duplication of pretty much the same
stuff all over the place.

Frankly, it looks to me that trying to design a complete solution for
everything would be really hard and time-consuming. I’d rather work
in “agile” way and start with just a couple of stacks; then factor out
commonalities and build from there.
Tomcat is the prime candidate since that’s what the "legacy"
application cookbook had; Glassfish may as well be a second example.

Andrea