1 2 3 Previous Next 35 Replies Latest reply on Dec 11, 2012 1:52 AM by nickarls Go to original post
      • 15. Re: How do you kill off a completed thread?
        sfcoy

        I see you're using DriverManager to get a database connection. You won't get any transactional semantics at all when you do that.

         

        You need to configure a JTA datasource in the server and inject it into your beans with @javax.annotation.Resource.

         

         

        {code:java}@Stateless

        @TransactionManagement(TransactionManagementType.CONTAINER)

        public class CustomerHarvesterThread {

            ...

            @Resource(lookup="configured/jndi/name/of/DataSource")

            javax.sql.DataSource ds;

            ...

         

            @Asynchronous

            public void ripCustomers() {

                  // Transaction has been started for you

                  ...

                  Connection conn = ds.getConnection();

                  try {

                       ... do sql stuff in a transaction

                  } finally {

                       conn.close();

                  }

                  ...

                  // Transaction will be committed upon normal method completion

            }

        }{code}

        • 16. Re: How do you kill off a completed thread?
          sfcoy

          Hmm.

           

          The javadoc says "Mark a singleton bean for eager initialization during the application startup sequence".

          • 17. Re: How do you kill off a completed thread?
            nickarls

            Yes, but it implies a "on everything else, nothing happens" ;-)

            • 18. Re: How do you kill off a completed thread?
              sfcoy

              I'll agree to disagree on that one...

              • 19. Re: How do you kill off a completed thread?
                tony.herstell1

                @Asynchronous worked a treat

                 

                I would agree that putting out a warning or error message to say that putting @Startup on a non @Singleton is not encouraged as its confusing enough as it is and every little bit helps.

                 

                I ditched the Events as kept getting warnings from Weld about missing scopes when trying to use them... this may explain:

                   CDI contexts are not propagated to new threads so you won't see them observed - Pete Muir

                 

                I do have my Database conenction set up in standalone-modeshape.xml, but its for the "nice" schema.

                 

                                 <datasource jta="true" jndi-name="java:/datasources/scramsadministratorDatasource" pool-name="scramsadministrator_pool" enabled="true" use-java-context="true" use-ccm="true">

                                    <connection-url>jdbc:mysql://localhost:3307/scramsadministrator</connection-url>

                                    <driver>mysql</driver>

                                    <security>

                                        <user-name>scramsadmin</user-name>

                                        <password>XXXXXXXX</password>

                                    </security>

                                    <statement>

                                        <prepared-statement-cache-size>100</prepared-statement-cache-size>

                                        <share-prepared-statements>true</share-prepared-statements>

                                    </statement>

                                </datasource>

                 

                For the connection to reap from the other database it was all READ ONLY and "messy" so I just used some simple JDBC to avoid having to incorporate it all into my project.

                 

                Pete has led the quickstats initiative; http://www.jboss.org/jdf/quickstarts/get-started/

                 

                Be great to see, say, an example that deals with this area.

                • 20. Re: How do you kill off a completed thread?
                  sfcoy

                  You will also find a lot of useful stuff at Adam Bien's Blog. His Java EE Patterns book is very worthwhile too.

                  • 21. Re: How do you kill off a completed thread?
                    tony.herstell1

                    I may have to.

                    This morning had @Asynchronous working in my "code" and now I don't sice I tried to incorporate some of your great suggestions.

                     

                    Created a singleton as suggested:

                     

                    @Singleton
                    public class CustomerHarvestFromXXXService implements Serializable {
                    

                     

                    put the Asynchronous method in it and now its not Asynchronous any more.

                     

                        @Asynchronous
                        public Future<String> run() {
                            String status;
                            this.logger.info(">>>Run");
                            this.clearErrors();
                            this.ripCustomers();
                            status = "Completed";
                            this.logger.info("<<<Run");
                            return new AsyncResult<String>(status);
                        }
                    

                     

                    moved the calling method to another controller (conversational bean) to no avail.

                     

                    public void getCustomers() {
                            this.logger.info(">>>getCustomers");
                            if ((this.future == null) || this.future.isDone()) {
                                this.customerHarvestFromXXXService.clearErrors();
                                this.future = this.customerHarvestFromXXXService.run();
                                this.postGlobalMessage("request_to_process_accepted", FacesMessage.SEVERITY_INFO);
                            } else {
                                this.postGlobalMessage("still_processing", FacesMessage.SEVERITY_INFO);
                            }
                            this.logger.info("<<<getCustomers");
                        }
                    

                     

                    this.future = this.customerHarvestFromXXXService.run(); <=== is; for some reason a synchronous call.

                    • 22. Re: How do you kill off a completed thread?
                      tony.herstell1

                      So, gave up on singleton again, and made it

                       

                      @Stateless

                      public class CustomerHarvestFromXXXService implements Serializable {

                       

                      That made @Asynchronous work again

                       

                      Popped in a few

                      @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)

                       

                      and seems all good.

                       

                      Not sure why Singleton wont work.

                      • 23. Re: How do you kill off a completed thread?
                        sfcoy

                        Your customerHarvestFromXXXService reference needs to have been injected by the container.

                         

                        If you used @Inject, maybe you need to use @EJB instead.

                        • 24. Re: How do you kill off a completed thread?
                          tony.herstell1

                          Thanks for your suggestion and support.

                          There is clearly confusion over EJB and CDI (and this is only likely to get bigger as they are due to diverge more as people want to run CDI outside of App servers).

                          This, to me, is very sad in that we "fixed" EJB through Spring and then Seam and now what????

                           

                          I have so much other stuff to write in such a short time that this indulgance must come to an end... It "works" though.. thanks to your support.

                          • 25. Re: How do you kill off a completed thread?
                            nickarls

                            Spring was nice because it kicked the JCP in their collective butts.

                             

                            However, the restrictions that are present in the EE specification are there for a reason and Spring in some cases made stuff work by allowing it in the simple cases and then going "you don't need it" when looking at more complex cases.

                            CDI contexts (the built-in ones) don't work like that because e.g. a request scope that hangs around forever is no longer a request scope. But you are free to create a custom scope with a custom lifecycle and still remain EE compliant without cheating ;-)

                             

                            I think the CDI/EJB/Managed Bean concepts are being harmonized more and more as we move into EE 7 and beyond.

                            • 26. Re: How do you kill off a completed thread?
                              tony.herstell1

                              >> I think the CDI/EJB/Managed Bean concepts are being harmonized more and more as we move into EE 7 and beyond.

                              You may want to tlak to the CDI lead about this.

                               

                               

                              Also, with a few more hours ferkeling I got the bean working, hopefully, as a Singleton with Container managed TXNs, with each "batch" being a new TXN (I cannot tell as the call to em.getTransation() is not allowed (exception) so I can't print out the TXN id out to see - may be useful to allow [String em.getTransactionId()] - HINT!).

                               

                              // Just want the one bean for the whole application.
                              @Singleton
                              public class CustomerHarvestFromXXXService implements Serializable {
                              

                               

                               

                                  @Asynchronous
                                  //@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
                                  public Future<String> run() {
                                      String status;
                                      this.logger.info(">>>Run");
                                      this.clearErrors();
                                      try {
                                          this.ripCustomers();
                                      } catch (Exception ex) {
                                          this.logger.severe(ex.getMessage());
                                          status = "Errored Out";
                                      }
                                      status = "Completed";
                                      this.logger.info("<<<Run");
                                      return new AsyncResult<String>(status);
                                  }
                              

                               

                               //@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
                                  private void ripCustomers() {
                                      this.logger.info(">>>ripCustomers");
                                      ... Nasty JDBC code to read some data into a Entity (unpersisited and sent into next call in batch mode)
                                      this.processXXXXXCustomerBatch(customersFromXXXInBatch);
                                      ...
                                  this.logger.info("<<<ripCustomers");
                                  }
                              

                               

                               

                                  // Lets start a new (very clean) transaction for handling each customer batch as we need to store the new "real" customer object
                                  // against the Territory (Don't want to do all the customers in 1 Trans as timeout will kick in)
                                  @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
                                  private void processXXXXCustomerBatch(Collection<SalesPoint> customersFromXXXInBatch) {
                              
                                      this.logger.info("Processing Batch...");
                                  ...
                                      this.em.persist(customer);
                                      this.em.flush();
                                  ...
                                 }
                              

                               

                              My hope is that @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) does what I want which is to start a new txn each time the "batch" routine is called.

                               

                               

                              This whole process is off a button click which backs onto a Conversational bean (Yes LOTS of people use Conversations!)...

                               

                              @URLMappings(mappings = { @URLMapping(id = "importCustomers", pattern = "/customer/import", viewId = "/pages/customer/importCustomers.xhtml") })
                              @Stateful
                              @ConversationScoped
                              // EL Can can find me...
                              @Named
                              public class CustomerHarvesterController extends BaseController implements Serializable {
                              

                               

                                  private Future<String> future;
                              
                                  @Inject
                                  private CustomerHarvestFromXXXService customerHarvestFromXXXService;
                              

                               

                              public void getCustomers() {
                                      this.logger.info(">>>getCustomers");
                                      if ((this.future == null) || this.future.isDone()) {
                                          this.customerHarvestFromXXXService.clearErrors();
                                          this.future = this.customerHarvestFromXXXService.run();
                                          this.postGlobalMessage("request_to_process_accepted", FacesMessage.SEVERITY_INFO);
                                      } else {
                                          this.postGlobalMessage("still_processing", FacesMessage.SEVERITY_INFO);
                                      }
                                      this.logger.info("<<<getCustomers");
                                  }
                              

                               

                               

                              I think a "Qucikstart" (with some explanation) may be a good idea... (if only so someone with more knowledge, in this area, can go through the process).

                               

                              (BTW I do make heavy use of the http://docs.oracle.com/javaee/6/tutorial and the JBoss Quickstarts).

                               

                              I may go-for-gold and put back in these as I HOPE they will stop these TXNS timing out (if they have one).

                              //@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)

                               

                              Also still need to figure out HOW to see if the this.customerHarvestFromXXXService.run() is running from another conversation(as the private Future should be conversational)... but for now, it will just have to wait. I hear a rumour that I could annotate  private Future as Application scope which would be useful as each Conversation can see the same variable...

                               


                              • 27. Re: How do you kill off a completed thread?
                                nickarls

                                Try a

                                 

                                @Resource

                                private UserTransaction ut;

                                 

                                and look at that one

                                 

                                As far as I know, the CDI (and EE groups) are aware of the Managed Bean dilemmas. They were already for EE 6 but there was no time to fix everything, I think.

                                • 28. Re: How do you kill off a completed thread?
                                  tony.herstell1

                                  That worked but just showed

                                  Transaction: org.jboss.tm.usertx.client.ServerVMClientUserTransaction@3d69140f

                                  for every batch.. so the same object.

                                   

                                  Seems to conflict with:@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)

                                  Which implies it should get a new one...

                                  • 29. Re: How do you kill off a completed thread?
                                    nickarls

                                    It might be a proxy. There is probably some non-portable way of getting the ID. Perhaps casting the UT to a ServerVMClientUserTransaction and see what it has to offer or look up the TransactionManager from jndi and cast the Transaction from there down to the implementation.

                                     

                                    Gottasleep, spent 1h of monday already :-/