11 Replies Latest reply on Jul 14, 2009 8:12 AM by Anton Belevich

    RichFaces 4.0 Core: Resources

    Nick Belaevski Master

      Hello all,

      Jay has asked me to write a short notes on RF 4.0 resources code; so here it is. Suggestions and opinions are highly welcome.

      First I've started with LegacyResourceHandlerImpl.java class.
      Its functionality is servicing resources using legacy API (InternetResourceBuilder/InternetResource). In order to be able to use these resource in JSF 2.0 tags/#{resource['...']} expression, I've created a LegacyResourceWrapper.java wrapper class - its only functionality is getRequestPath() method that encodes URI for legacy resource.

      The main difference in JSF 2.0 and RF 3.3.x resources is that RF resources mostly service (sends HTTP headers and data) themselves. That's so because dynamically generated resources are written directly to OutputStream by ImageIO API; so there's no way to provide InputStream without using some kind of buffering. We have caching services, however not all resources are cacheable by definition. In JSF 2.0, resources servicing is done by ResourceHandler class that reads map containing headers and instance of InputStream class just from resource and then transfers the information to the client.

      After measuring memory consumption I've decided to introduce buffering even for non-cached resources in order to increase performance (just think about bytes necessary to hold the whole raster image in memory vs. the same image bytes, but compressed to PNG/GIF; note that image bytes are not reclaimed until the whole image is written and slow clients are highly possible). Additionally, this allows to get more closer to JSF 2.0 resources API. So, here is the updated version of RF Resource implementation ResourceImpl.java

      There's a handler that does the job of servicing resources. Resources are searched as classes extending Resource class in TCCL: ResourceHandlerImpl.java

      Special interface for the user to plug in his own encoder/decoder for dynamic data (in RF 3.3.x there are two ResourceBuilder implementations - the first that encodes to zip-crypt-base64 and the second that saves data in cache): ResourceCodec.java

      Utility class that assists in resources processing stuff and holds the code that both implementations of ResourceHandler share: Util.java

      Working example of dynamic image resource: TestResource2.java

      Another changes committed are mostly about refactoring Legacy API: switching from HttpServletRequest to ExternalContext. Couple of classes was deprecated, I'd like to discuss their future in the context of PortletBridge also.

      Current issues/questions:

      1. Are we going to support legacy API - do we need LegacyResourceHandlerImpl?
      2. Caching issues - there are some well-known caches (I've experimented with EhCache; JBoss cache is next to try) that do the actual cache fill job in the separate thread (using internal thread pool); however resources generation code may request the stuff bound to the web application thread (e.g. FacesContext; also I have some suspects about TCCL validity). We can cope with the problem by introducing thread pool that will do all cache operations and calling back resource methods in the context of web application thread - JDK 5 has all necessary synchronization primitives to make this very easy to implement; however that does not look like a very good thing for me. Cloning thread context is possible, but also seems a hack. What do you think?
      3. In RF 3.3.x there was only one way for the resource in the application cache to be regenerated - to be purged when cache size limit was reached. I suggest that we use "expires" resource data for that; so that resource will expire simultaneosly in HTTP caches and application cache.
      4. Password for the crypted resources can be found because we use the same one for the framework data (it has fixed value known to the user; i.e. values of skins parameters) and user data. So, the possibility of defining a set of passwords for the different cases looks like not a bad idea.
      5. I haven't set up logging yet, so there are a lot of e.printStackTrace()/TODOs for logging. Are we going to use java.util.Logger or some logging framework, e.g. SLF4J?

      Thanks for reading!

        • 1. Re: RichFaces 4.0 Core: Resources
          Nick Belaevski Master

          2) EhCache is capable of doing the right thing; I'm investigating JBoss Cache now.

          In any case, I'm thinking about getting rid of home-grown cache - is it ok to make JBoss Cache or EhCache a required dependency for RichFaces?

          • 2. Re: RichFaces 4.0 Core: Resources
            Jay Balunas Master

            I would certainly prefer JBoss Cache in this situation unless there are good reasons not to.

            Also for logging I talked with Pete about the webbeans-logger project. It has limited dependencies and would be worth taking a look at. If that has issues lets go wth SLF4J.

            • 3. Re: RichFaces 4.0 Core: Resources
              Nick Belaevski Master

              Ok, draft and very basic support for JBoss Cache checked in.

              Also checked in draft support for resources versioning.

              • 4. Re: RichFaces 4.0 Core: Resources
                Anton Belevich Novice

                Hi all,

                We could use webbeans logger. As I understand SLF4J has a serious limitation it ships with several jar called 'bindings' which provides access to various loggers (log4j, commons-logging, java.util.logging) and only one from those binding jar could be in the appropriate classpath so user have to always add new binding jar and remove old if he want use another logger ... I'm going relocate webbeans logger classes into the shaded richfaces artifact. But I don't know yet which is the right place for it richfaces-api or richfaces-impl :)

                • 5. Re: RichFaces 4.0 Core: Resources
                  Jay Balunas Master

                  Hi Anton,

                  I'm confused by what you mean by "relocate" webbeans logger classes? Or the "shaded" richfaces artifact?

                  If we go this route I would assume we would just pull in wb-logger as a maven dependency.

                  As far as SLF4J that is good to know, although I'm not sure that is enough to no use it. We can ship with the "binding" jar that we suggest and that would allow others to swap it out if wanted to. Do you think that would be ok?

                  • 6. Re: RichFaces 4.0 Core: Resources
                    Anton Belevich Novice

                    Hi Jay,

                    We'll have to ship richfaces libraries with wb-logger jars if we pull in wb-logger/SLF4J as a maven dependency I think this is not good idea.
                    Also I think to have JDK logger and log4j support is enough. I propose move wb loggers classes from wb jars to our impl (or api) jar using shade maven plugin.




                    • 7. Re: RichFaces 4.0 Core: Resources
                      Jay Balunas Master

                      I do not like the idea of just making a copy of the webbeans code to avoid it as a dependency. If we use SLF4J, log4j, etc... we would also need to pull in those jars.

                      It is ok if we ship the jars we are dependent on - like logging code, and other 3rd party dependencies.

                      We need a better way to handle logging without just implementing it ourselves, or cut/paste code from another source. Ideally we want to tie into what ever logging mechanism the users are using. It is my impression that SLF4J helps us to do that because of the different binders. Can you investigate that a little more?

                      Also if we go with straight JDK logger, or log4j we tie ourselves to it, while if we use a proxy like wb-logger or SLF4J our options for support go way up.

                      • 8. Re: RichFaces 4.0 Core: Resources
                        Anton Belevich Novice

                         

                        Can you investigate that a little more?


                        ok I'll investigate this more on Monday.


                        • 9. Re: RichFaces 4.0 Core: Resources
                          Anton Belevich Novice

                          Hi Jay,

                          I did investigation so here are results:

                          1. SLF4J: http://www.slf4j.org
                          supports for the next logging frameworks (logback, log4j, JUL (java.util.Logging), Simple logger impl, NOP, JCL (Jakarta Commons Logging);
                          *pros: supports multiple logging frameworks.
                          *cons: have to ships SLF4J with richfaces libraries, need one and only binding jar in the classpath

                          2. wb logging:
                          supports (JUL, log4j).
                          *pros: we ships only richfaces libraries
                          *cons: limited logging frameworks support, need to relocate compliled wb classes in to the richfaces libraries

                          3. log-bridge: https://log-bridge.dev.java.net/
                          supports (Simple Log, JUL, log4J, IBM's Logging Toolkit for Java, jLo, Protomatter Syslog)
                          *pros: supports multiple logging frameworks, easy implement your own bridge for another logging package.
                          *cons: have to ships log-bridge libraries with richfaces, need explicitly set what logging package will be used.

                          4. Our own implementation ...

                          comments?

                          • 10. Re: RichFaces 4.0 Core: Resources
                            Jay Balunas Master

                            Good investigation - my comments are inline.

                            "abelevich" wrote:

                            1. SLF4J: http://www.slf4j.org
                            supports for the next logging frameworks (logback, log4j, JUL (java.util.Logging), Simple logger impl, NOP, JCL (Jakarta Commons Logging);
                            *pros: supports multiple logging frameworks.
                            *cons: have to ships SLF4J with richfaces libraries, need one and only binding jar in the classpath


                            From what I've seen many frameworks are using SLF4J and/or migrating to it (including wb). I don't mind shipping 3rd party dependent libraries with RichFaces - it makes it easier for people to package their apps. As for the binding requirements they are runtime only, and seem pretty simple to integrate. These will also let us just "use" what ever logging the target app is using.


                            2. wb logging:
                            supports (JUL, log4j).
                            *pros: we ships only richfaces libraries
                            *cons: limited logging frameworks support, need to relocate compliled wb classes in to the richfaces libraries


                            This is assuming we copy class files into richfaces. I do not like this approach. If we are going to use wb-logger we need to use the dependency. At the same time this is not desirable because we could have a perceived dependency on wb that may turn people off.

                            Web beans is also going to be implementing and using SLF4J in their logger, so might not be buying much by using webbeans logger.


                            3. log-bridge: https://log-bridge.dev.java.net/
                            supports (Simple Log, JUL, log4J, IBM's Logging Toolkit for Java, jLo, Protomatter Syslog)
                            *pros: supports multiple logging frameworks, easy implement your own bridge for another logging package.
                            *cons: have to ships log-bridge libraries with richfaces, need explicitly set what logging package will be used.


                            I'm not too familiar with the log-bridge, but it seems to have the same basic functionality as SLF4J. The difference is just in how you set core logging library - log-bridge = property, SLF4J = classpath.

                            My opinion is that we go with SLF4J and more forward.

                            • 11. Re: RichFaces 4.0 Core: Resources
                              Anton Belevich Novice

                              ok, I'll setup SLF4J for the logging.