2

I have an application scoped bean to hold the information in my database. After its instantiation it should fetch the data, so I annotated the method with @PostConstruct. As soon as I request the jsf page where this bean is referenced the server log explodes! I think it somehow recurses and the only stacktrace I get is that a System Exception occurred during the repBean.acceptVisitor(Visitor); method. The server log then gets several GB big and I have to manually delete it in order to have free disk space. If I delete the @PostConstruct annotation there are no exceptions. After calling the update() method from another bean the repositoryContent variable is updated properly and contains the information. The only problem then is that my jsf page doesn't display the content for some strange reason.

@ManagedBean(eager=true)
@ApplicationScoped
public class IndexBean implements Serializable {

    private ArrayList<ViewFolder> repositoryContent;

    @EJB
    RepositoryService repBean;

    @PostConstruct
    public void update() {
       RepositoryVisitor Visitor = new RepositoryVisitor();
       repBean.acceptVisitor(Visitor);
       repositoryContent = Visitor.getList();
   }
}
BenMorel
  • 34,448
  • 50
  • 182
  • 322
nico1510
  • 606
  • 9
  • 29
  • What does `acceptVisitor()` do? By the way, the phrase *"As soon as I request the jsf page where this bean is referenced the server log explodes!"* is strange in first place. This bean is supposed to be constructed during server startup, not during first request. Is the `@ApplicationScoped` been imported from the right package? – BalusC Oct 24 '12 at 20:29
  • @BalusC Why would it be constructed during server startup? I'm not a CDI expert, but my understanding of `@ApplicationScoped` was that the bean instance should be created once when first needed and then stored in the context for subsequent requests, not that it should necessarily be created when the application/server starts. – Brett Kail Oct 24 '12 at 20:57
  • 1
    @bkail: there's an `eager=true`. Without it, it would indeed be constructed on 1st request only. – BalusC Oct 24 '12 at 20:58
  • @BalusC Got it, thanks. I obviously don't know much about JSF MB either :-). – Brett Kail Oct 24 '12 at 21:00
  • Yes youre right I forgot that I added the eager true. With eager true, I think I remember that the error messages came directly after deployment and without they came at request but I cant tell for sure because I cant access the server log because it really explodes. @BalusC : the acceptvisitor method opens a connection to a repository and lets the repository accept the visitor. But this method works without any errors if I call it not within the postconstruct method so I think the problem lies somewhere else – nico1510 Oct 24 '12 at 21:08
  • Well, there must be some recursion. I can imagine of a possible cause that the `acceptVisitor()` or `getList()` indirectly evaluates the EL expresison `#{indexBean}` which in turn constructs the bean again, because it's not been placed in service yet (this happens only *after* (post)construction. In the newly constructed bean, the `@PostConstruct` will be invoked again, etc..etc.. Infinite loop. – BalusC Oct 24 '12 at 21:10
  • Oh and @ApplicationScoped is imported from the faces package... – nico1510 Oct 24 '12 at 21:10
  • Yes you are right recursion in this method would explain the huge server log I will check if I can find the cause for that – nico1510 Oct 24 '12 at 21:13
  • Putting a debug breakpoint in `@PostConstruct` method would also help. The IDE should pause there anyway, giving you the opportunity to explore the call stack who invoked it and why. – BalusC Oct 24 '12 at 21:15
  • ok there's absolutely no dependency between the RepositoryBean+visitor and the IndexBean... The only thing I can think of is that my jsf page is the problem. In the jsf page I have several references to it like this : #{Indexbean.downloadFile(param)} Note: there are also some methods in the bean. But since its application scoped it should be instantiated only once no ? – nico1510 Oct 24 '12 at 21:29

1 Answers1

2

This is not normal behaviour.

One of the following lines

   RepositoryVisitor Visitor = new RepositoryVisitor();
   repBean.acceptVisitor(Visitor);
   repositoryContent = Visitor.getList();

is indirectly evaluating the EL expression #{indexBean} which in turn causes the bean being constructed once again, because it is not been put in service yet. It would only be put in service (and thus available as a concrete #{indexBean}) when the @PostConstruct finishes. This all causes an infinite loop.

You might need to do some refactoring, or to pass the application scoped bean instance itself to the method call so that it can be used directly instead of being referenced by an EL expression.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Ok there is an @Inject reference within the EJB repBean. This explains why there is recursion with eager=true. Because the IndexBean uses the repBean in its postconstruct method and before this method ends the repBean gets injected and within the repBean the indexBean gets injected and so on... But why does this also happen without the eager attribute ? – nico1510 Oct 24 '12 at 21:46
  • 1
    Ah so, there's cyclic reference. You'd need to break this through. Inject the one in the other only, not also the other way round. As answered, if the other also needs to perform task on the current instance, pass it as method argument instead. I'm still not sure which line is offending, but most likely you'd need to remove the `@Inject` in the EJB and then pass it as `repBean.acceptVisitor(this, Visitor);` instead. – BalusC Oct 24 '12 at 21:48
  • Yes that's it! Basically I need the indexBean within the repBean for other method calls so passing it for this method as an argument would be no solution but I think I'll find another way to solve this from here. Thank you very much for your help ;-) – nico1510 Oct 24 '12 at 22:04
  • is it also possbile to lazyly inject the indexBean within my EJB so that it is only instaniated as soon as it is first needed? – nico1510 Oct 25 '12 at 08:13
  • @BalusC Google really should extend "site:stackoverflow.com" and add support for "site:stackoverflow.com;answerFrom:BalusC" ;-) – dognose Sep 29 '14 at 18:14
  • @dognose Duh! This serves me the purpose: site:stackoverflow.com "balusc" desired keywords here – developer10 Oct 06 '16 at 11:09
  • 2
    @developer10: you can also target an user in the search here. E.g. http://stackoverflow.com/search?q=user%3A157882+postconstruct – BalusC Oct 06 '16 at 11:15