6 Replies Latest reply on Feb 14, 2009 12:28 AM by modoc

    Stateless session bean and mod-proxy-ajp

    haim

      Hi


      I have a strange problem with stateless session bean and mod-proxy-ajp. (or is it just me being newbie?)


      I have a very simple session bean with one method. I've read that although this is statelss session bean, seam is smart enough to hold the variables until the next page finishes to redraw. indeed, this is the case when I access jboss directly.


      The problem starts when I access jboss through apache and mod-proxy-ajp. I don't see the result variable. The method finishes correctly, but I see blank where the EL variable should be. The proxy is configured like this:



      ProxyPass /someplace/ ajp://localhost:8009/someplace/




      It's even more complicated then that because I access this session bean also from a WebService. (which works fine in both cases).


      If I change this session bean to be statefull it works, but I don't want SESSION context and I don't want the overhead of accessing CONVERSATION context from WebServices.


      Any ideas how to solve this?


      Thanks


      Haim

        • 1. Re: Stateless session bean and mod-proxy-ajp
          keithnaas

          How close is your setup to the instructions on UsingMod_proxyWithJBoss?


          • 2. Re: Stateless session bean and mod-proxy-ajp
            haim

            Keith Naas wrote on Mar 03, 2008 09:42 PM:


            How close is your setup to the instructions on UsingMod_proxyWithJBoss?




            Well. not so close, since I'm not using any form of load balancing stuff. there's only one jboss and one apache, so (I think) there's no need for the sticky sessions and other load balancing stuff. The only setting I have is the one I've showed in the post.


            Thanks.


            Haim

            • 3. Re: Stateless session bean and mod-proxy-ajp
              haim

              Hi


              I've create a simple project to demonstrate this problem.


              To use it do the following:



              1. download http://www.babysnakes.org/project.zip and open it.

              2. install maven 2.0.8 from http://maven.apache.org/

              3. cd into the project folder and run mvn package.

              4. deploy ear/target/statetest.ear (on linux) or ear\target\statetest.ear (on windows) to jboss.

              5. go to http://localhost:8080/statetest/request.seam

              6. Fill your name and press sayHello. you should see usual The result was: hello, name.

              7. Configure apache with
                ProxyPass /statetest ajp://localhost:8009/statetest


              8. Now go to http://localhost/statetest/request.seam and you'll get only The result was: (without hello, name).



              Any Ideas?


              Thanks


              Haim

              • 4. Re: Stateless session bean and mod-proxy-ajp
                modoc

                I'm having what may be a related issue.


                I am using Seam 2.1.1 GA, and JBoss 4.2.3.GA (same on JBoss 4.2.2.GA).


                My application has PAGE scoped action class that handles a form submission.  It creates a Job entity and persists it.  I am using FlushModeType.MANUAL and flushing the entitymanager.  It then raises an asynchronous Seam event, which passes the Job.id.  A conversation (although I've played with other scopes) scoped Seam Component Observes that event, and then uses entityManager.find(Job.class,jobId) to load up the Job, and then processes the job (something that takes several minutes).


                When I hit JBoss directly, this works perfectly 100% of the time.  However, if Apache is in front of JBoss, the entityManager.find returns null.  This is true regardless if I'm using mod_proxy http or mod_proxy_ajp.  All other parts of my application work as expected.


                Any ideas on how to fix this and/or work around it?


                • 5. Re: Stateless session bean and mod-proxy-ajp
                  modoc

                  Relevant code:



                      @SuppressWarnings("unchecked")
                      @Begin(nested = true, flushMode = FlushModeType.MANUAL)
                      public String createJob() {
                       this.mLog.info("Starting createJob method.");
                       // Add null/empty validations
                       if (StringUtils.isBlank(this.mNewCouponJob.getName())) {
                           this.facesMessages.add("Please enter a name for the new Coupon Job");
                           return null;
                       }
                       if (this.currentCampaign == null) {
                           this.facesMessages.add("Please go back and select a campaign again.");
                           return null;
                       }
                       final List<Campaign> existing = this.entityManager.createQuery(
                            "select j.name from couponJob j where j.name=:name").setParameter("name", this.mNewCouponJob.getName())
                            .getResultList();
                       if (existing.size() == 0) {
                           ((Session)this.entityManager.getDelegate()).setFlushMode(FlushMode.MANUAL);
                           this.mNewCouponJob.setDate(new Date());
                           this.mNewCouponJob.setUser(user);
                           this.mNewCouponJob.setCampaign(currentCampaign);
                           this.mNewCouponJob.setComplete(false);
                           this.mNewCouponJob.setGenerated(0);
                           this.entityManager.persist(this.mNewCouponJob);
                           this.entityManager.flush();
                           this.entityManager.refresh(currentCampaign);
                           this.entityManager.clear();
                  
                           Events.instance().raiseAsynchronousEvent("newCouponJobCreated", mNewCouponJob.getId());
                  
                           setLastCreatedJobId(mNewCouponJob.getId());
                           this.facesMessages.add("You have successfully created Job #0", this.mNewCouponJob.getName());
                           setNewCouponJob(new CouponJob());
                           return "couponJobCreated";
                       } else {
                           this.facesMessages.add("Coupon Job name #0 already exists, please pick another", this.mNewCouponJob
                                .getName());
                           return null;
                       }
                      }
                  




                      @Transactional
                      @Observer("newCouponJobCreated")
                      @End
                      public void handleNewCouponJob(final int pCouponJobId) {
                       this.mLog.info("handleNewCouponJob was called with job id: #0.", pCouponJobId);
                       long startTime = System.currentTimeMillis();
                       entityManager.joinTransaction();
                       ((Session) this.entityManager.getDelegate()).clear();
                       ((Session) this.entityManager.getDelegate()).setFlushMode(FlushMode.MANUAL);
                       entityManager.flush();
                       entityManager.clear();
                       final CouponJob job = this.entityManager.find(CouponJob.class, pCouponJobId);
                  




                  pages.xml


                       <page view-id="/coupon/campaign.xhtml" login-required="true">
                            <rewrite pattern="/campaign/{campaignId}" />
                            <rewrite pattern="/campaign" />
                            <param name="campaignId" value="#{campaignDetail.selectedCampaignId}" />
                            <navigation from-action="#{campaignFormHandler.createJob}">
                                 <rule if-outcome="couponJobCreated">
                                      <redirect include-page-params="true" view-id="/coupon/job.xhtml">
                                           <param name="jobId" value="#{campaignFormHandler.lastCreatedJobId}" />
                                      </redirect>
                                 </rule>
                            </navigation>
                       </page>
                  
                  
                       <page view-id="/coupon/job.xhtml" login-required="true">
                            <rewrite pattern="/job/{jobId}" />
                            <rewrite pattern="/job" />
                            <param name="jobId" value="#{jobDetail.selectedJobId}" />
                       </page>
                  




                  • 6. Re: Stateless session bean and mod-proxy-ajp
                    modoc

                    Nevermind, this appears to be related to timing between the event being picked up and the redirect finishing allowing the conversation to end, and the db commit taking place.