Re: [RT] Accessing environment information in 2.2
Simone Gianni wrote: Hi Carsten, maybe I'm missing something, but isn't there a ProcessInfoProvider, with which you can access request, response, servlet context and object model (and from there all the rest)? Yes, this is one part of the story. If you're able to get the ProcessInfoProvider everything is fine. The question is, how can you get this component if your code is not inside a component/bean? So my idea is to get the request attributes through a thread local (spring already provides a mechanism for this), get the application context from the request attributes (we already put the application context into the request attributes) and then get the process info provider from the application context. Carsten -- Carsten Ziegeler - Chief Architect http://www.s-und-n.de http://www.osoco.org/weblogs/rael/
Re: [RT] Accessing environment information in 2.2
Hi Carsten, maybe I'm missing something, but isn't there a ProcessInfoProvider, with which you can access request, response, servlet context and object model (and from there all the rest)? It ends in a thread local anyway, since uses the environment stack Daniel told about. If this is not the right class, then maybe we should revise the javadocs, since the ContextHelper (which was used in 2.1 to access all other stuff from a Contextualizable component) is deprecated and the ProcessInfoProvider is suggested instead. Simone Carsten Ziegeler wrote: During development you sometimes face the problem that you need access to specific information, like the current request object (or its parameters), the Spring application context, the servlet context etc. In an ideal world where everything is a component, this is no issue as the container provides a way for this. But as we all know, the world is not ideal and this means, you sometimes need access to those objects when you don't have anything else to use. So, I think we need a way to provide those information. The best choice seems to be to use thread local variables. I think we need a way to access the servlet context, the original http request/response object and the current application context. (If you have access to the current request object, you can get the application context from the request). The provide access to those things from everywhere the best way is to have a general servlet filter putting the information into thread local variables and cleaning them after the request is finished. This approach has the drawback that users have to put this filter into their web.xml. So I think we should make this a little bit more user friendly and add the logic/code of this filter to all servlets we provide by default (which means the servlet performs the code). So as long as users are using our servlets, they get the information for free. In addition, we provide the servlet filter for users who might want to use different servlets but need the same information. WDYT?
[RT] Accessing environment information in 2.2
During development you sometimes face the problem that you need access to specific information, like the current request object (or its parameters), the Spring application context, the servlet context etc. In an ideal world where everything is a component, this is no issue as the container provides a way for this. But as we all know, the world is not ideal and this means, you sometimes need access to those objects when you don't have anything else to use. So, I think we need a way to provide those information. The best choice seems to be to use thread local variables. I think we need a way to access the servlet context, the original http request/response object and the current application context. (If you have access to the current request object, you can get the application context from the request). The provide access to those things from everywhere the best way is to have a general servlet filter putting the information into thread local variables and cleaning them after the request is finished. This approach has the drawback that users have to put this filter into their web.xml. So I think we should make this a little bit more user friendly and add the logic/code of this filter to all servlets we provide by default (which means the servlet performs the code). So as long as users are using our servlets, they get the information for free. In addition, we provide the servlet filter for users who might want to use different servlets but need the same information. WDYT? -- Carsten Ziegeler - Chief Architect http://www.s-und-n.de http://www.osoco.org/weblogs/rael/
Re: [RT] Accessing environment information in 2.2
Carsten Ziegeler skrev: During development you sometimes face the problem that you need access to specific information, like the current request object (or its parameters), the Spring application context, the servlet context etc. In an ideal world where everything is a component, this is no issue as the container provides a way for this. But as we all know, the world is not ideal and this means, you sometimes need access to those objects when you don't have anything else to use. Can you give some specific examples where you need this? So, I think we need a way to provide those information. The best choice seems to be to use thread local variables. This is a dangerous path to follow. Thread locals make it very hard to reuse objects or unit test them. I spent a far to large part of the weekend getting rid of the use of the environment stack in the AbstractProcessingPipeline (not checked in yet, I'm waiting until after the milestone release). This to make the pipeline reusable. It was really hard work to understand what was going on in the code. I realize that thread locals might be necessary in a few specific cases. But as they make the code really hard to understand and unit test I don't feel happy at all about providing some general mechanism for it. Of course the users of Cocoon should be free to do any mistakes they feel like, but we don't need to provide them tools for doing it. I think we need a way to access the servlet context, the original http request/response object and the current application context. (If you have access to the current request object, you can get the application context from the request). Spring has some kind of request scope for beans together with a servlet filter for setting up the scope it has also mechanisms for keeping dependencies on request scoped beans up to date. This is a fairly structured and controlled way to handle request scoped information. And it keeps DI and testability. Would it be enough for your needs? The provide access to those things from everywhere the best way is to have a general servlet filter putting the information into thread local variables and cleaning them after the request is finished. This approach has the drawback that users have to put this filter into their web.xml. So I think we should make this a little bit more user friendly and add the logic/code of this filter to all servlets we provide by default (which means the servlet performs the code). So as long as users are using our servlets, they get the information for free. In addition, we provide the servlet filter for users who might want to use different servlets but need the same information. I don't see any need for such extra magic. For users who don't want to care about web.xml, we provide a default one that will be enough for most needs. For users who care, it shouldn't be any problem to manage some filters. WDYT? Sorry to be negative, but global variables is really an anti pattern. So I'd like to discuss the specific problem and see if we can find a cleaner solution first. /Daniel
Re: [RT] Accessing environment information in 2.2
Daniel Fagerstrom wrote: Can you give some specific examples where you need this? We often have the problem to get the current service manager. The whole code base contains various calls to the EnvironmentHelper class to get this service manager. One main reason for this are utility methods like we have in the SourceUtil class. A caller of these utility classes should not need to get the container just in order to call the utility stuff. Another problem in this area is that components might be able to get the container they were declared in, but not the current container. This is for example important when you're running in a sub sitemap. Then we have various occasions were someone needs some information from the request object, like the current uri or some request parameter or to use this to create an http servlet request wrapper to call some other stuff. Now, one solution is of course to pass the request object down to the place where you need it, but this of course would mean that your implementation might have an impact on your interfaces which is not really nice. This is a dangerous path to follow. Thread locals make it very hard to reuse objects or unit test them. I spent a far to large part of the weekend getting rid of the use of the environment stack in the AbstractProcessingPipeline (not checked in yet, I'm waiting until after the milestone release). This to make the pipeline reusable. It was really hard work to understand what was going on in the code. Yes, I agree - and 2.2 contains a cleanup version if this stuff... :) Spring has some kind of request scope for beans together with a servlet filter for setting up the scope it has also mechanisms for keeping dependencies on request scoped beans up to date. This is a fairly structured and controlled way to handle request scoped information. And it keeps DI and testability. Would it be enough for your needs? Hmm, not sure - I have not really looked into this stuff. But from my understanding Spring is using ThreadLocals for this as well :) Sorry to be negative, but global variables is really an anti pattern. So I'd like to discuss the specific problem and see if we can find a cleaner solution first. To be honest, I'm happy to discuss this stuff with someone. Ok, rethinking a little bit, what about making the current request object available? This contains the current container as an attribute and it's possible to get everything else from the container. Carsten -- Carsten Ziegeler - Chief Architect http://www.s-und-n.de http://www.osoco.org/weblogs/rael/
Re: [RT] Accessing environment information in 2.2
Hi Daniel, Carsten, Carsten Ziegeler skrev: During development you sometimes face the problem that you need access to specific information, like the current request object (or its parameters), the Spring application context, the servlet context etc. In an ideal world where everything is a component, this is no issue as the container provides a way for this. But as we all know, the world is not ideal and this means, you sometimes need access to those objects when you don't have anything else to use. Can you give some specific examples where you need this? We have similar needs. For using REST-style POST and PUT request with blocks it is neccessary to copy the original request input stream to a new block request, so it would be helpful to be able to access the original request at this point of time. Another use case is copying request parameters when using blocks. I'm sure Alexander can give you some more details. I think we need a way to access the servlet context, the original http request/response object and the current application context. (If you have access to the current request object, you can get the application context from the request). Spring has some kind of request scope for beans together with a servlet filter for setting up the scope it has also mechanisms for keeping dependencies on request scoped beans up to date. This is a fairly structured and controlled way to handle request scoped information. And it keeps DI and testability. Would it be enough for your needs? If there is a solution for this problem that does not uses global variables, we should go for it. Lars -- Lars Trieloff visit http://www.mindquarry.com/
Re: [RT] Accessing environment information in 2.2
Carsten Ziegeler skrev: Daniel Fagerstrom wrote: Can you give some specific examples where you need this? We often have the problem to get the current service manager. The whole code base contains various calls to the EnvironmentHelper class to get this service manager. For those in the audience that don't know all about Cocoon internals: The environment helper contains a thread local stack. Each time a sitemap is entered the current environment and processor (containing a reference to the local service manager of the sitemap) are pushed on the stack. The information is poped when the sitemap is left. The reason for using the environment helper is that we need to lookup some components relative to the service manager of the sitemap that currently is executed, rather than relative to the service manager that the currently executed component happened to be defined in. The most prominent example of where we need this is for the source resolver. The way it works today is that the component calls e.g. the static method EnvironmentHelper.getSitemapServiceManager(). While this works it breaks IOC and makes it much harder to unit test the component or to reuse it outside the Cocoon sitemap. It also makes the code really hard to follow. A more abstract way to express the above is that we want some (uses of) components, e.g. the current source resolver, to have *sitemap scope*. E.g. what source resolver we get depends on what sitemap that currently is executed. In Spring 2.0 there is a mechanism called bean scopes that solves this problem. There are a number of provided bean scopes: singleton, prototype, request, session and global session (http://static.springframework.org/spring/docs/2.0.x/reference/beans.html#beans-factory-scopes). It also allows for custom scopes. We could implement a sitemap scope (and a block scope). With this we could define the sitemap scoped source resolver as: bean id=oac...currentSourceResolver class=oac...CocoonSourceResolver scope=sitemap !-- dependecies ... -- aop:scoped-proxy/ /bean Then e.g. a pipeline can depend on it: bean id=oac...pipeline class=oac...CachingProcessingPipeline scope=prototype property name=currentSourceResolver ref=oac...currentSourceResolver/ !-- dependencies ... -- /bean The element aop:scoped-proxy creates a proxy for the current source resolver that delegates to the actual current source resolver when a dependent component use it. Behind the scene the implementation of a sitemap scope will still use a thread local call stack that needs to be pushed while entering a sitemap and poped while leaving. But the components does not have to know anything about this anymore, they are pure DI components that are easy to understand, reuse and unit test. The above (probably) requires that we deavalonize the affected beans and make the DI POJOs instead. But IMO we should start do deavalonize Cocoon core anyway. One main reason for this are utility methods like we have in the SourceUtil class. A caller of these utility classes should not need to get the container just in order to call the utility stuff. I agree that it is more convenient to not need to use the container, but I don't think the consequences make it worthwhile in the end. Another problem in this area is that components might be able to get the container they were declared in, but not the current container. This is for example important when you're running in a sub sitemap. sitemap scope! Then we have various occasions were someone needs some information from the request object, like the current uri or some request parameter or to use this to create an http servlet request wrapper to call some other stuff. Now, one solution is of course to pass the request object down to the place where you need it, but this of course would mean that your implementation might have an impact on your interfaces which is not really nice. You might guess my opinion about this by now ;) Anyway Spring has a RequestContextListener, RequestContextHolder combo that might be reused for this. It just handles the request attributes, but the needed parts of the request object could be put in some attributes. Spring has some kind of request scope for beans together with a servlet filter for setting up the scope it has also mechanisms for keeping dependencies on request scoped beans up to date. This is a fairly structured and controlled way to handle request scoped information. And it keeps DI and testability. Would it be enough for your needs? Hmm, not sure - I have not really looked into this stuff. But from my understanding Spring is using ThreadLocals for this as well :) It certainly does (not much choice I guess). But the point is that it embeds it in such away that the components still can use pure IOC, no need for the components to pull any info from static methods. Sorry to be negative, but
Re: [RT] Accessing environment information in 2.2
Daniel Fagerstrom wrote: I think that a sitemap scope could solve a large part of our needs. Hmm, yes, together with the RequestContextHolder from Spring it should solve most of our problems. The RequestContextHolder makes only the attributes of a request available. Fortunately we already store the current spring container in an attribute and we have the ProcessInfoProvider bean which can be used to get access to the current http request/response object and the current Cocoon object model. Together with using a sitemap scope, I think this is sufficient. Carsten -- Carsten Ziegeler - Chief Architect http://www.s-und-n.de http://www.osoco.org/weblogs/rael/