Schaible, J�rg wrote:
Hi Steve,All dressed up and nowhere to go!
[...]
The URL analysing service is something we already have and Iwill havo integrate this into the webapp. So I assume I had to modify some of the DefaultXXX classes to convert my servlet into something that is part of the component logic.
In principal you should not need to extend anything (at least tha't the objective). The URL side really only comes in play when the servlet is handling dynamic content presentation. An HTTP request can include a service identifier and parameters. The servlet directs the request to a service running in Merlin which can then handle the request resolution. This works really nicely and makes for really compact code in the web-app - but more about this later in the week.
Well, we have really some very special URL encoding and - since the code analysing the URL already runs - I would just like to avalonize it. My problem is that I am running out of time for the start-up phase. If you can give me a hint how to install my contoller servlet as Merlin block (or whatever) or a way to handle the request over to a component I will be happy. If I can replace code later on with a better and much more geenralized solution - fine. Currently I am feeling like a moron - with your demo I have a wonderful running component logic running inside my webapp - but I cannot access it anyway <g>!
Sounds to me like we need to publish the root block into a JNDI context, have this picked up by the servlet, update plock to provide access to appliances (and through appliance acess to services). I think I mentioned in an earlier eemail that the is a JNDI API that is being seperated out of the Tomcat project. Noel (James project) ws discussing this a few weeks ago - he probably has more details. This is probably the fastrack solution and gets us som useful content in the process. If you or someone else can take this on I can sort out the block expose of appice references and/or services.
[...] But with Merlin I seem to have a lot of running threads communicating with each other for every single request.
You mixing up threads on avaon Dev with threads in Merlin ;-)
Gotcha. Somehow I had the impression that every component is running in its own thread - possibly just a result of the one-component-per-block samples :)
Not following this. Merlin creates one thread per container so I don;t see where the "lots-of-threads" is comming from.
Now anything comes right in the place.
Good.
You can achieve instance-per-servlet instance by using the transient policy. This means that a new instance is created per request - i.e. your servlet is in control - it get the service once, caches it for the duration fo the servlet lifetime and releases it on servlet disposal.If you running one thread per request you may want to look at the per-thread lifecycle policy. This policy ensures that a new component instance is created once per-thread. There is an example of the per-thread componet in the playground. Default lifestyle behaviour is singleton (i.e. thread safe componet).Hmmm. What means "singleton" in the context of a servlet. The servlet container is free to create any number of instances of my servlet calling the same servlet instance concurrently. The servlet instances itself will normally not be destroyed until the servlet container terminates, but even this is part of the vender's implementation strategy. So, normally I would define a singleton as a class with exaclty one instance independent of any thread - which might not be true in this context here. I assume this means one instance per servlet instance, which suits perfectly.
To declare a per thread policy all you need to do is add an attribute to the .xinfo file for the component you want to be per-thread. Here is an example:Learned something new again :)
<type>
<info>
<name>my-component</name>
<attributes>
<attribute key="urn:avalon:lifestyle" value="thread"/>
</attributes>
</info>
</type>
(Although I have the impresion that someone will really have to collect all these urn-keys in one big overview table <g>)
Wow - that so close to volunteering .... :-)
I'm assuming that you will Merlin is one servlet, and from that servlet you will will publish services or blociks or whatever in a name context which will be accessible by other servlets in you application. As far as the rott/manager environment - there are a couple of mecahnuism for enabling Merlin's access to jars - (a) autodiscovery via classloader scanning, (b) autodiscovery via extension directories, and (c) explicit refernece to the file system - but this can be problamatic if your not in control of the deployment environment. You should keep in mind that unlike Tomcat, you cannot package jar files into a block at this time - due to a JDK bug on embedded jar loading into a classloader - which basically means writting your own classloader or caching embedded jars on the file system. The last approach is what I would to see in place in the near future.[...]
Just for reference - case (b) was non-discovery of the component because of non-discovery of the jar file - but that will not be a problem because the engine automaticaly scans all of the jar files in the classloader heirachy when first initialized.
Hmm. Is there any way to read directly from the file system? The block.xml gives me the class names of the services. The files are already in the classpath and all I would need is to load the .xinfo using getClass().getClassLoader().getResource(). Because building every time a jar and deploying it to the servlet engine would be much more effort than using code replacement features during debug.
If I wanted to do so I think I have to provide an overloaded DefaultRepositoryManager. This is only possible by overloading EngineClassLoader overloading createResourceManager and therefore an own DefaultKernel instanciating the overloaded engine ... or I need another DefaultBlockLoader that inistailizes this overloaded <sigh>Eeek, eeek, eek.
You should not need to do any of the above. If we do this right - the active servlet will gain access to a service via something explosed in a naming context (you can even stick it into application vairable for testing purposes). All you client needs to do is ask for the service - that it - the rest will just happen (once we have the service publication bit is done).
From the command lineDid not work. Stepping through the code, the kernel initializes a bootstrapLoggingManager from an entry "urn:assembly:logging.descriptor" and I am not quite sure, what it expects in the xml file for a descriptor (and it does not work either, for the context below). Here is the simplified code (omitting try/catch blocks) from the kernel initialization:
$ merlin -debug
From an embedded scenario - when you contextualize the kernel you can control the default logging priority by passing in a conext entry "urn:merlin:debug" - with a value of a String with the logging priority level (e.g. "info", "warn", "error" or "debug"). The command line -debug option just passes in the "debug" string to the DefaultKernel context.
================ snip =============
final DefaultLocator lContext = new DefaultLocator( );
lContext.put( "urn:merlin:debug", "DEBUG" ); // "debug" does not work either
lContext.put( "urn:merlin:home", lHome );
lContext.put( "urn:merlin:classloader.common", this.getClass( ).getClassLoader( ) );
lContext.put( "urn:merlin:classloader.system", this.getClass( ).getClassLoader( ) );
lContext.put( "urn:merlin:kernel.profile", lProfile );
lContext.makeReadOnly( );
Configuration lConfig = lConfig = getConfiguration( lProfile );
m_kernel.contextualize( lContext );
m_kernel.configure( lConfig );
m_kernel.initialize( );
m_kernel.start( );
================ snap ===============
A grep through the sandbox code did not show any occurence of "urn:merlin:debug" ... when did you implement this?
Last couple of days - - ok, I'm checking.
Apart from that you can control logging priority for any appliance or block declared in your blocks.xml file using the <categories/> element.Hmm. I tried the entry within the root block, but no effect, I do not get debug output :(
<categories priority="WARN"/>
The above declaration set the logging priority for whateve is enclosing it to the declared level. In the following example the logging level is set to INFO and a child logger called my-sub-channel is set to DEBUG.
<categories priority="INFO"/>
<category name="/my-sub-channel" priority="DEBUG"/>
</categories>
Here is a practical example in which I'm setting different logging levels at the block and appliance levels.
<block name="demo">
<implementation>
<!-- set the logging level for the root block to WARN-->
<categories priority="WARN"/>
<appliance name="standard" class="org.apache.avalon.playground.StandardComponent" activation="startup">
<!-- set the logging level for this component to DEBUG -->
<categories priority="DEBUG"/>
</appliance>
<container name="test">
<!-- set the logging level for this container to ERROR-->
<categories priority="ERROR"/>
<appliance name="standard" class="org.apache.avalon.playground.StandardComponent" activation="startup">
<!-- set the logging level for this component to INFO -->
<categories priority="INFO"/>
<context class="org.apache.avalon.playground.StandardContextImp"/>
<configuration>
<message>Standard component inside a nested block.</message>
</configuration>
</appliance>
</container>
</implementation>
</block>
Here is the output:
====================== snip ======================
[INFO ] (sys): initialization from: C:\Work\demo\head\src on localhost
[WARN ] (sys): directory scanning not supported: file:/C:/demo/head/bin/
[WARN ] (sys): directory scanning not supported: file:/C:/demo/head/bin/
[INFO ] (sys):
commencing block construction phase
[INFO ] (sys): block count = 1
[ERROR ] (sys): Message: Block installation phase failure.
===================================================================
Exception: org.apache.avalon.merlin.block.BlockException
Error during block deployment for block: 1 [test]
Cause: org.apache.avalon.merlin.block.BlockException
Cannot build the container descriptor: test
Cause: org.apache.avalon.merlin.container.ContainerException
Root container in block: test contains an profile that references an unknown type: demo.service.HelloWorld
Cause: org.apache.avalon.assembly.engine.type.UnknownTypeException
demo.service.HelloWorld
====================== snap ======================
And here the current block.xml:
====================== snip ======================
<block>
<implementation>
<categories priority="DEBUG" />
<appliance name="standard" class="demo.service.HelloWorld" activation="startup">
<configuration>
<message>Hello World block descriptor.</message>
</configuration>
</appliance>
</implementation>
</block>
====================== snap ======================
Quite strange.
Smells like a bug ... I'll dig. As to the exception - is you .xinfo in your jar file? Cheers, Steve. -- Stephen J. McConnell mailto:[EMAIL PROTECTED] http://www.osm.net --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
