One more piece to include is inlined below:
--Nikolaos
Nikolaos Giannopoulos wrote:
All,
I wanted to offhand thank everyone who provided insight and tips on
how to resolve this issue. As Ben, Aaron and Frank pointed out there
is a disconnect between Spring initialization and the Stripes filter
initialization. After a lot of googling and listening to advice and
some great code out on the Internet I have a solution that I am happy
with. Project uses JPA + Spring + Stripersist + Hibernate + other
stuff....
Problem Description:
---------------------------
Leverage @SpringBean, @Service, @Repository, @Autowire, etc...
annotations with minimal ApplicationContext.xml configuration (just
component scans) AND have Spring beans perform post-creation
initialization that involves making calls through Stripersist without
throwing exceptions e.g. initializing DAO's that provide pick lists... .
Problem Overview:
-------------------------
Placing the following in web.xml results in Spring reading the
ApplicationContext.xml and wiring of Spring defined and annotated
beans...
<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>
However Stripersist is only initialized - much later - once the
StripesFilter is initialized and moreover that will only occur on
initial request filter processing therefore performing any sort of
initialization that depends on Stripersist in the a Spring bean's
constructor OR in in a @PostConstruct OR whatever will result in
possible exceptions as Stripersist has not had its init(config) method
invoked yet to initialize itself.
2 Solution Alternatives:
------------------------------
#1 Somehow force Stripersist to have its init(config) method invoked
PRIOR to Spring initialization.
#2 Somehow perform delayed initialization on the beans that would
like to initialize themselves AFTER Spring and Stripersist init
Solution #1 - "the easy solution"
-----------------------------------------
A rather simple way to do this is to define a bean at the top of
ApplicationContext.xml that simply calls a class with the following
code in its constructor:
(new Stripersist()).init((Configuration) null);
Null is passed in above as normally one would pass in
StripesFilter.getConfiguration() however as the Stripes Filter has not
been initialized yet the result is null anyways along with a debug
logging exception being harmlessly displayed.
However this has a few drawbacks besides being a kludge... the primary
one being that when Stripersist gets its chance to initialize as part
of the Stripes Filter initialization... persistence.xml, entity
manager factories et al. will ALL be recreated a 2nd time which is
quite expensive... not to mention Stripersist will spew a
NullPointerException we should trap around the code above.
Despite the drawbacks... the above will allow our @PostConstruct
method to call Stripersist methods and all is well... though the
solution is clearly a dirty hack...
Solution #2 - "the longer IMHO more elegant solution"
---------------------------------------------------------------------
There are MANY ways to do this I simply present ONE way....
Create a new annotation called say @DelayedInitialize that is
associated with the methods in the Spring beans that need to say call
Stripersist or anything e.g.:
@DelayedInitialize
public void initService() {
List<Modality> modalityList = this.modalityDao.findAll();
this.modalityCache = new ModalityCache();
this.modalityCache.init(modalityList);
}
Include the following line in ApplicationContext.xml to make sure the
@DelayedInitializerRunner listens to ApplicationEvent's:
<bean id="delayedInitializer"
class="org.lightagents.ws.annotation.DelayedInitializerRunner" />
Have this annotation's runner listen to Spring ContextRefreshedEvent
(which means that Spring has finished building its Application Context
BUT does not mean that Stripes Filter OR transitively Stripersist has
initialized yet) and retain methods annotated with this annotation in
a static list. Also this annotation's runner should allow for a
static initializeNow() method call that simply iterates over the
static list and fires the annotated methods.
A REALLY useful piece of code to use to model this is provided here
and provides the framework for a similar premise... adding
@PostInitialize to Spring:
http://issues.springframework.org/browse/SPR-5966?page=com.atlassian.jirafisheyeplugin%3Acrucible-issuepanel
(Thanks to Baruch Sadogursky and zvizvi for putting this code together)
Lastly, how to trigger this delayed initialization. Well one could
create a dummy filter to run after Stripes filter but an even easier
solution is leveraging a hook allowed for by Stripersist itself which
essentially allows custom init code to be executed as the last step of
Stripersist init(config). The class is simply as follows:
public class StripersistDelayedInitialize implements StripersistInit{
@Override
public void init() {
DelayedInitializerRunner.initializeNow();
}
}
So here is what happens in a nutshell:
a) Spring creates the Application Context leveraging
ApplicationContext.xml and Spring beans are created and wired...
b) Once the Context is created Spring fires the ContextRefreshedEvent
ApplicationEvent which is picked up by our DelayedInitializerRunner
and invokes code that finds all the @DelayedInitialize annotations and
creates a static list of those method calls
c) Stripes Filter initializes and as part of that initialization
Stripersist initializes and as part of that initialization our simple
class triggers the initializeNow method statically on our
DelayedInitializerRunner which causes the static list of methods to
call to be invoked one by one
Lastly, although the @DelayedInitialize is being used in the context
of code that needs to execute AFTER Stripersist is initialized the
code is generic enough that it could be used for other purposes as
well... i.e. wherever any methods that need to be called at some later
point in time is involved.
Thanks Again to everyone who responded!
HTH,
--Nikolaos
------------------------------------------------------------------------------
_______________________________________________
Stripes-users mailing list
Stripes-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/stripes-users