Announcement Announcement Module
Collapse
No announcement yet.
Getting access to ServletContext from the Service layer Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Getting access to ServletContext from the Service layer

    I'm looking for advice on how to provide access to the ServletContext in the Service layer.

    To be precise, I need to have access to a few informations given by the ServletContext, like the rela path of the deployed webapp.
    I'd rather avoid any dependency of the Service layer on Servlet API, but I don't see how I could inject properties of the ServletContext in my AbstractService at runtime.

    thanks for any tips
    -jean

  • #2
    Try with ServletContextFactoryBean or ServletContextAttributeFactoryBean or with #{contextAttributes.myKey} if you are using spring 3.x (see javadoc)

    cheers
    Last edited by chelu; Sep 24th, 2009, 10:43 AM.

    Comment


    • #3
      You should never, ever do that! Your service absolutely MUST be agnostic of its clients and their implementation details. The service lives in a completely different architectural tier, and, potentially, may be used by more than one application, and various clients. What you are trying to do is a violation of the most basic architectural principle. So, if you need some front-end parameters to be passed to the service, you may pass them with a call to the service API.

      If you need the service to cache and store the relative path of the web application, or some sort of a "doc root" concept, you can have some initialization method on the service that will set this value once and for all, and call that method once from your front-end when appropriate. However, your service - in a well designed system - should not even know that it is being used by a web application.

      Comment


      • #4
        The a service layer only exposes a property for conifiguration. A WebApplicationContext loads beans on service layer and configure them using contextAttributes bean or ServletContextAttributeFactoryBean.

        I don't see any problem on this.

        cheers.

        Comment


        • #5
          Originally posted by chelu View Post
          The a service layer only exposes a property for conifiguration. A WebApplicationContext loads beans on service layer and configure them using contextAttributes bean or ServletContextAttributeFactoryBean.

          I don't see any problem on this.

          cheers.
          My response was to the original post. The bottom line is: the presentation tier must take care of setting the value on the service - whichever way best suits the purpose - instead of the service querying a presentation-tier entity.

          Comment


          • #6
            thanks for the answer.
            My base abstract service now extends ServletContextAware for convenience. But I agree it should not have any reference to the Servlet API.
            I wanted to use ServletContextFactoryBean to get the aplication absolute path, but this is deprecated in Spring 3.0.

            I'll wait for a GA before migrating my code to something better.

            cheers,
            -jean

            Comment


            • #7
              Originally posted by Jean View Post
              My base abstract service now extends ServletContextAware for convenience.
              I am sorry to say this, but that is just absolutely horrible.

              One of the most important things that a good software engineer should aim to develop is a sense of good code/design. That sense should serve as the guiding light in everything you design. If something doesn't feel right, you just don't accept it and keep looking for a better solution that is always there to be found. (Eventually, you will see that a good solution is guaranteed to cut the development time in the long run.) If you don't see the problem with your "solution", the kind of problem that makes it absolutely unacceptable, it is not good. However, the fact that you obviously felt uneasy with that approach and posted a question is a good sign. I'd definitely recommend re-thinking your design - for the sake of the project, and, most importantly, for the sake of your own learning experience. There are plenty of easy ways to solve the problem by defining some tier-agnostic domain object that would hold some generic "parameters", populating that bean in the front-end and passing it to (setting it on) the service(s). You can do it with an aspect, for example.

              Comment


              • #8
                constv, i'm really happy you take the time to insist on this point! And I totally agree, architectural design is very important and generally not stressed on enough.

                I'm here fixing an application developed by a beginner that has been left alone for months. I've got to fix it from bottom to top. And I'm starting from the top actually 'cause that's where the most important issues lies.
                I'll have to come to fix this service dependance on Servlet API later, and that'll be as soon as Spring3.0 gets to GA since I don't want to either code a solution that will be deprecated soon or code a solution that won't be able to roll out in production.
                That's a small issue, we only need to be able to get the absolute application path for now, and the solution is already better than the hardcoded "c:\" in the JSPs!

                I've noticed you were in favor of passing parameters to the service layer. My service level methods almost all have an HttpServletRequest parameter. Mostly to get access to info store in the request/session.
                I find it horrible and would really like to find something nicer. The way to go seem to avoid that seem to use TheadLocal. (although AOP could probably help). Unfortunately I'm really not familiar with the concept. I probably have to do some background reading on ThreadLocal, but if you'd know some good resources on this, that could help me eliminate all those nasty request parameters. It'd be very helpful.

                Comment


                • #9
                  Originally posted by Jean View Post
                  I've noticed you were in favor of passing parameters to the service layer. My service level methods almost all have an HttpServletRequest parameter. Mostly to get access to info store in the request/session.
                  I find it horrible and would really like to find something nicer. The way to go seem to avoid that seem to use TheadLocal. (although AOP could probably help). Unfortunately I'm really not familiar with the concept. I probably have to do some background reading on ThreadLocal, but if you'd know some good resources on this, that could help me eliminate all those nasty request parameters. It'd be very helpful.
                  When I say "parameters", I mean a completely tier-agnostic, ordinary Java class (domain entity or DTO) that serves simply as a container for either hard-coded attributes or a generic collection of name/value pairs that would make sense for the application service layer. For example, you can call it ConfigParams, or whatever. if your service layer needs to know the root path to the documents on the file system, your domain object with parameters would contain either a "String docRoot;" attribute or a map entry with key "docRoot" and the value of the actual path. The client will populate that object and pass it to the service. The service would easily extract the data it needs without being aware of any notion of the client's implementation detail, e.g. the fact that the client is a servlet. The bottom line: both application layer and front-end can share the knowledge of the business domain concepts (e.g. "documents root" would be a generic concept), but the middle tier should never make any assumptions regarding the implementation/technology/details of its clients.

                  Btw, the proper/safe way to use ThreadLocal would be to still pass the value from the servlet/controller to the middle-tier service via the service API, and then - if you really need to use the value in the middle-tier in many methods without passing it as a parameter to each method - attach it to ThreadLocal.

                  hth
                  C

                  Comment


                  • #10
                    Hi constv,

                    I got you clearly when you speak about parameters. And that's how I do it when I need to pass information only obtainable from the front tier to the middle tier.
                    But my point is precisely to find something not more efficient, but let's say more elegant in order to avoid adding parameters to each every method of the service layer.
                    As for the application root path, it's pretty nice to be able to inject it at runtime to the main services. Spring allows that and this is a once-for-all piece of information.

                    But as for HttpServletRequest, I find it really a hell to have to pass it as a parameter to each every service layer. And I am actually surprise that you can write "if you really need to use the value in the middle-tier in many methods without passing it as a parameter to each method".
                    I mean that's not a "need" but to me it obviously looks like a way better method to achieve the same goal.

                    So I'm actually wondering why this pattern is actually not more widespread. Are there any inconvenience in using ThreadLocal? Or maybe it's me that hasn't been following the trend...

                    -jean

                    Comment


                    • #11
                      Originally posted by Jean View Post
                      But my point is precisely to find something not more efficient, but let's say more elegant in order to avoid adding parameters to each every method of the service layer.
                      No, you certainly should not pass it to every API. When did I say that. I said that such parameters (if they never change) should be set once on the service. But my point is that 1) it is not the service that request that data; 2) when the data is set on the service during its initialization or shortly after (by the application), there should be no notion of the implementation detail of the client communicated to the service. In other words, your service must be designed agnostic of HTTP servlets, portlets, web, etc. And, of course, as always with DI, how the value is passed to the service must not be a concern of a service at all. You will just have a setter on the service and that's it. That is my point. Now, dependig on when exactly the data becomes available to the application, there are different ways to inject it into the service, by the framework or client itself.

                      But as for HttpServletRequest, I find it really a hell to have to pass it as a parameter to each every service layer. And I am actually surprise that you can write "if you really need to use the value in the middle-tier in many methods without passing it as a parameter to each method".
                      I mean that's not a "need" but to me it obviously looks like a way better method to achieve the same goal.

                      So I'm actually wondering why this pattern is actually not more widespread. Are there any inconvenience in using ThreadLocal? Or maybe it's me that hasn't been following the trend...

                      -jean
                      This depends on whether your logic that uses a particular value is consolidated, or the value is used by many classes in the middle tier. I assumed that, once you set your "doc root path" as a stored property of your service instance, you would use it only within your service class, ideally consolidated within a single private (or protected) method through which other methods might use it. It is a good rule to always limit the scope of a variable as mush as possible. Just as with using global variables, you need to think twice before attaching something to ThreadLocal. Also, if your value is the same for all threads, why would you want to re-assign the same value to each and every thread? Using ThreadLocal may make sense when tracking some user context info specific to a particular user action/request, for example, but not with application parameters, like global file paths.
                      Last edited by constv; Oct 2nd, 2009, 06:51 AM.

                      Comment


                      • #12
                        here's one simple solution...

                        Define a singleton bean (a generic domain class, not a presentation tier class) - in your Spring app context - that will serve as a container for any "global" parameters that you want to be shared between potentially any other spring-managed beans. (Don't necessarily populate it by setting values of its attributes, if the data is only available at run-time.) Inject a reference to that bean into whatever Spring-managed beans/services that might need it, as well as into your servlet context (using Spring's ServletContextAttributeExporter bean definition.) Then, whenever the data in question becomes available to your web application, simply have your web app (controller) pull the bean from the servlet context and set values on it. That's it. Since the services store references to that object, they will have access to whatever you put in it. You have to make sure that your web app populates that "shared" param container before it calls any service API, obviously. It's very simple, and no architectural principles are violated. (Perhaps, Spring already offers something similar out of the box, I may be unaware of it. But, in any case, it's very simple.)

                        hth

                        Comment

                        Working...
                        X