8 Replies Latest reply on Dec 20, 2008 12:08 AM by vgriffin

    null log inside framework.Controller

      I'm instantiating EntityHome<Tbl> directly rather than through the annotation. I wrap it around an instance of Tbl so I can persist, remove, or update the Tbl instance. The code is similar to:

           @Logger
           private Log log;
           
           // create around an instance we're marking as clean
           public TblHome(Tbl tbl) {
                super();
                if (log == null)
                {
                     System.out.println("null log");
                     log = Logging.getLog(this.getClass());
                }
                super.setInstance(tbl);
                TblId id = tbl.getId();
                if (id == null)
                {
                     id = new TblId();
                     tbl.setId(id);
                }
                assignId(id);
                clearDirty();
           }

      When I do the database operation, it invokes framework.Home.createdMessage or something similar. That invokes framework.Controller.debug which finds a null log and fails.

      I can override the method using my log, but I shouldn't have to. Of course all output methods in Controller use log.debug, etc, so it's not just a matter of overriding the getLog method.

      Is there a clean way to do this where Controller will find a real log?
        • 1. Re: null log inside framework.Controller

          See this thread, you only hope right now is to use an iframe or frames.

          • 2. Re: null log inside framework.Controller

            Ups, that post was for another thread, sorry

            • 3. Re: null log inside framework.Controller

              Valerie Griffin wrote on Dec 15, 2008 23:14:


              I'm instantiating EntityHome<Tbl> directly rather than through the annotation.


              Instantiating directly rather than through the annotation disables annotation based injection. In this cases, it disables @Logger.



              Is there a clean way to do this where Controller will find a real log?



              Yes, do not instantiate directly




              • 4. Re: null log inside framework.Controller
                Your answer is condescending and dismissive, not at all informative. I consider it to be a bug for Controller to generate NPE if code instantiates the TblHome directly and calls persist or whatever. I found at least one other reference to a similar NPE that someone else had gotten some time ago. If you examine forum messages, you will see that others have tried the same thing.

                I need something with TblHome functionality without the edit page. In one case, I need to allow the user to delete entries directly from the list. This is complicated a little by the need to use a modal panel to confirm the delete. The TblHome class has a remove method so I wrote a quickDelete method in TblHome which can be called directly from TblList.xhtml using a RequestParameter or from TblList.quickDelete().

                The code inside TblList is:

                     public void quickDelete() {
                          hideDeleteConfirmPanel();
                          TblHome home = new TblHome();
                          home.setTblIdParm(tblIdParm);
                          home.quickDelete();
                     }

                The code inside TblHome is:

                     public void quickDelete() {
                          setTblId(tblIdParm);
                          wire();
                          if (isManaged()) // in case it sets anything we need
                               remove();
                     }

                This is clean, functional code that is easy to maintain. It permits TblHome to be the only class that changes TBL items in the database. The ONLY problem it has is that I have to change the constructor to allow for a null log:

                     public TblHome() {
                          super();
                          if (log == null)
                          {
                               System.out.println("null log");
                               log = Logging.getLog(this.getClass());
                          }
                     }

                and override the debug method:

                     protected void debug(Object object, Object... params)
                     {
                          log.debug(object, params);
                     }

                I can accept the constructor change far more easily than I can accept the need to change the debug method.

                Elsewhere, I create or modify Tbl entities and want to use TblHome to persist or update them.

                If there is a way to cause this sort of instantiation without losing the annotation, then you can tell me what it is instead of telling me not to do something that solves my immediate problem.
                • 5. Re: null log inside framework.Controller
                  joblini

                  Hi Valerie,


                  You cannot instantiate a Seam component directly using the new operator.  Among the correct methods are:



                  • inject the component using @In(create=true).

                  • call Component.getInstance.




                  • 6. Re: null log inside framework.Controller
                    joblini

                    For your situation in may be more convenient to instantiate the component from page.xml, for example,



                    <?xml version="1.0" encoding="UTF-8"?>
                    <page xmlns="http://jboss.com/products/seam/pages"
                          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                          xsi:schemaLocation="http://jboss.com/products/seam/pages http://jboss.com/products/seam/pages-2.1.xsd"
                          no-conversation-view-id="/login.xhtml"
                          login-required="true">
                       
                         <begin-conversation flush-mode="MANUAL" join="true" />
                    
                         <param name="stakeholderId" value="#{stakeholderHome.stakeholderId}"/>
                       
                         <action execute="#{stakeholderHome.wire}" />
                    
                    </page>
                    


                    • 7. Re: null log inside framework.Controller
                      I cannot do the instantiation in page.xml because I am avoiding a page transfer.

                      I didn't find documentation that really covers what I'm trying to do. I'm certainly willing to try the Component route, but I've got questions about the lifetime of anything I create that way. When I do the quickDelete, the conversation only needs to encompass the delete operation. That use is probably the cleanest for trying the "right" way. I do need the assurance that there won't be anything left from a previous quickDelete made from the same screen.

                      Other times, I need to wrap my EntityHome<Tbl> around a specific instance of the Tbl entity. I could probably live with creating one instance of EntityHome<Tbl> and changing its underlying instance (including linking in the Id and marking it as clean) if I knew that would work.

                      What are the ramifications of using Component.newInstance vs Component.getInstance?

                      One of the reasons I decided to create the EntityHome<Tbl> instance is that there's a constructor in the generated code. This strongly suggests that it's okay to define and use constructors. I still maintain that it's a bug for the code to fail because of a side-effect in the way log is used internally.

                      I do appreciate your suggestions and will try them when I've got a little time for experimentation. Right now, I'm working on a very tight deadline.
                      • 8. Re: null log inside framework.Controller
                        I've got some code that SEEMS to be working, but I don't know if there arre hidden "gotchas".

                        Inside quickDelete, I'm using:

                            TblHome home = Component.getInstance("tblHome");

                        I've replaced the code to construct a wrapped instance with a static method inside TblHome:

                            // create around an instance we're marking as clean
                            static public TblHome wrapInstance(Tbl tbl) {
                                TblHome home = (TblHome)
                                        Component.getInstance("tblHome");
                                home.setInstance(tbl);
                                TblId id = tbl.getId();
                                if (id == null)
                                {
                                    id = new TblId();
                                    tbl.setId(id);
                                }
                                  
                                home.setId(id);
                                home.setInstance(tbl);
                                home.clearDirty();
                                  
                                return home;
                            }

                        If I run into any problems with this, I'll post them.