1 2 3 Previous Next 40 Replies Latest reply on Dec 20, 2006 2:28 AM by vk101

    Basic Seam questions

      What is the difference between injecting an entity into a session bean and instantiating it manually? They both seem like they work, provided that you use the appropriate EntityManager methods, such as persist().

      What is the main advantage of using injection versus not?

      I also have a question about @In(create=true). Wouldn't you always want create=true? For the first request, wouldn't injection always need to create the nonexistent entity? So I'm getting confused on when you'd want to not have create=true.

      Hopefully somebody could please clarify for me. Thanks.

        • 1. Re: Basic Seam questions
          smokingapipe

          There are subtle differences here. I'll go through your post sentence-by-sentence.

          When you inject an entity into a session, you could get an instance that already exists. For example, here's injection:

          @In User user;

          and here's instantiating it manually:

          User user = new User();

          These do totally different things. In the injection case, we'll be getting the user, perhaps from the SESSION scope, and so we can do things with it. In the "instantiating manually" case we make up a new one every time. Do you see the difference? They are for different purposes.

          @In(create=true) will inject the entity if it can be found in the relevant scope, and creates it if it isn't there. When wouldn't you want to have create=true? Imagine a typical application where a User object is stored in the SESSION scope. If there is no user in that scope, we might leave out certain functionality. Creating a new user instance wouldn't make sense.

          Does this make sense? Think of your session beans as being parts of an assembly line. Various objects get injected into them, they do things to these objects, and then they can outject results. If a certain part on this assembly line requires an object that isn't there, it could (unlike in a real assembly line) create the object by saying create=true. Or if it will ALWAYS create its own objects for its own use it could simply instantiate them. But this means that it will not get objects that have been outjected by some other component, and the power of Seam is really being able to tie these various components together by outjecting from one and injecting to the other.

          • 2. Re: Basic Seam questions

            That's a really good answer, thanks.

            I now have a question for when the different things on the "assembly line" are not different session beans, but different action methods on the same session bean.

            Because it's the same session bean, how does this impact when you need to inject or outject? For example, if you have a User entity that is used by multiple action methods on the same session bean, I'm guessing you would of course inject it using @In...but would you need to outject it using @Out as well?

            I ask because it's the same session bean, so is there a need to outject?

            Also, is there any major downside to outjecting every variable? It seems like you could outject every variable for use in session beans (parts of the "assembly line") that you will develop at a later time?

            Thanks.

            • 3. Re: Basic Seam questions
              gavin.king

              If you want to change the value of the variable, you need to outject. Otherwise the old value will be re-injected next time the component is invoked!

              There is probably no really major downside, no. Seam could probably have a single @ContextVariable annotation instead of @In @Out.

              • 4. Re: Basic Seam questions

                Some questions below:

                1) Could somebody describe the difference between the Seam-Managed Persistence Context that I've been reading about and the regular persistence contexts (Transaction and Extended)? Which one is it more similar to, and what should a Seam user know about it?

                2) If you have an entity whose fields you populate over several steps in a conversation, business process, or just a session, would you need to avoid validation annotations like @NotNull?

                I tried it and, after the first step in the multi-step process, it expectedly says that you're violating a null condition (because you've entered only a few fields and not all). Is there any way to get around this, short of moving everything to a single page or getting rid of annotations...or is this just a downside of such multi-step processes?

                3) If you have an existing entity that is detached, what's the difference between calling EntityManager.persist and EntityManager.merge? Is persist simply not meant to be used in such a case (though couldn't it find the current existing row in the database using the primary key of the Java entity and update that row based on changes)?

                • 5. Re: Basic Seam questions
                  gavin.king

                  1) A Seam persistence context is most like a container-managed extended persistence context. But whereas the container-managed context is tied to an SFSB instance, and hence there can be multiple contexts per conversation, the Seam persistence context has exactly one per conversation.

                  2) No, you can still use Hibernate Validator, just use an atomic persistence context, and be careful about where you put s:validate(All)


                  3) persist() does not accept detached entities (it throws an exception).

                  • 6. Re: Basic Seam questions

                    Must @Remove and @Destroy always be on the same method?

                    I still can't tell whether they are used to indicate to the container what to do when the annotated method (it would be have to be a business method) is called, or whether they are callbacks in that the method (a cleanup sort of method) is called by the container when it is about to do something...things I've read seem to lead me in both directions.

                    • 7. Re: Basic Seam questions
                      smokingapipe

                      It looks to me like @Remove and @Destroy are on the same method in all the examples I have seen. I never do anything in that method. It's just there. The only time I can imagine doing something in the @Remove @Destroy method would be, say, to cancel a registration that hasn't been completed before the timeout, for example, by removing the incomplete reg data from the DB.

                      • 8. Re: Basic Seam questions

                        Okay, so are you supposed to call that method? Based on @Remove, aren't you supposed to call a method marked with that annotation to signify the end of the stateful conversation?

                        I tried this (i.e. putting @Destroy @Remove on a business method that I call) which then gives an error about how the bean no longer exists (probably because it was just destroyed).

                        • 9. Re: Basic Seam questions
                          smokingapipe

                          No, when a conversation ends, the @End method is called. Not all stateful session beans are conversation scoped, in which case they wouldn't even need an @End. But you are right, if there's some task that needs to happen at the end of a conversation, the @End method would be the right place to do it.

                          So I'm not sure where the @Destroy @Remove method is used for anything. I don't think it's used in any of the examples I have seen, but it must be present.

                          • 10. Re: Basic Seam questions

                            I have made a simple example below that doesn't seem to be working. It creates an entity (Person) over two independent JSF action methods:

                            @Stateful
                            @Name("register")
                            public class RegisterBean implements Register {
                            
                             @PersistenceContext(type=EXTENDED)
                             private EntityManager em;
                            
                             @In(create=true) @Out
                             private Person person;
                            
                             private String firstName;
                             private String lastName;
                            
                             public String firstName() {
                            
                             person.setFirstName(getFirstName());
                            
                             em.persist(person);
                            
                             return "success";
                            
                             }
                            
                             public String lastName() {
                            
                             person.setLastName(getLastName());
                            
                             em.merge(person);
                            
                             return "success";
                            
                             }
                            
                             @Remove
                             @Destroy
                             public void destroy() {
                            
                             }
                            
                            }


                            I have a few questions on this example, but first, am I doing this correctly? Do I have the persist() and merge() in the correct places? Or should I remove the persist() and merge() and just have one persist() in lastName() - assuming lastName() is the second method to be called?

                            Is an EXTENDED persistence context correct here?

                            I'm getting an error in the second method, saying that "Exception during INVOKE_APPLICATION(5): javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value: "

                            Here's the problem. When I call the firstName() method, followed by the lastName() method, the lastName() method seems to create a brand new Person. This Person gets a lastName, does not pick up the firstName from the previous method invocation, and triggers a PropertyValueException because of the validation annotation on the entity...whoa!

                            What am I doing wrong? Any help would be greatly appreciated. Thanks.

                            P.S. I don't call the destroy() method anywhere in the code at all. And, while I define destroy in the business interface, I don't define the annotations there...should I?

                            • 11. Re: Basic Seam questions
                              gavin.king

                              The @Destroy method is called by Seam. The application does not need to call it. Any SFSB should have an @Destroy @Remove method so that Seam can destroy the bean when the context ends.

                              • 12. Re: Basic Seam questions
                                gavin.king

                                If you have an extended persistence context, and a conversation, you don't need to use merge.

                                But what is really wrong with your code is that you should be starting a conversation with @Begin on firstName() and ending it with @End on lastName().

                                • 13. Re: Basic Seam questions

                                  That works, thanks.

                                  1) I've left my destroy() method as in the example from the previous post. What I don't understand, though, is don't @Remove and @End conflict in any way? It seems like if @End is called, the conversation ends, and if @Remove is called, then the SFSB is removed? But I never call @Remove...

                                  The Seam tutorial says SFSB must have an @Destroy @Remove method...but it seems like @Remove does one thing and @Destroy does another. Why must they both be defined on the same method?

                                  2) When using conversations, is it required to use a stateful session bean as opposed to stateless? What about an extended persistence context as opposed to a transaction-scoped one?

                                  3) From the earlier posts about the Seam-Managed Persistence Context, how do I use it? What should I set @PersistenceContext(type=???????) to?

                                  4) Is there a way to catch any exception from an action method and return a certain string, such as "failure"? I could place a catch block inside every action method, but that seems like a pain.

                                  Is there some way to specify (through XML or annotations) that if a certain or any exception is thrown, that you simply return a certain value from the action method?

                                  • 14. Re: Basic Seam questions
                                    gavin.king

                                    1) You don't need to call @Remove, since Seam will call the @Destroy method, which removes the bean, at the end of the conversation.

                                    The reason for @Destroy @Remove is to make sure that the conversation can't possibly be destroyed without the SFSB being removed.

                                    2) No, it is definitely not required. There is nothing wrong with having a bunch of stateless actions all using the same conversation-scope persistence context. This is part of the magic of Seam - components with different scopes can all work smoothly together in a loosley coupled way, with no need for orchestration by the Java code.

                                    3) If you are trying to use a Seam-managed persistence context, do *not* use @PersistenceContext, use @In instead.

                                    4) Try using exceptions.xml:

                                    http://docs.jboss.com/seam/1.1GA/reference/en/html/events.html#d0e3695

                                    1 2 3 Previous Next