[ 
https://issues.apache.org/jira/browse/TAP5-795?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Peter Stavrinides updated TAP5-795:
-----------------------------------

    Description: 
It is mentioned in the documentation that the order in which services are 
created is not defined when using eagerLoad(). This is somewhat counter 
productive in a sense as you can get into serious trouble If ordering of 
eagerloaded services is important (and very often it is, as the very concept 
implies ordering and availability before other services), yet ordering is 
ignored for eagerloaded services? 

So by using :
binder.bind(SomeService.class).eagerLoad(); you can produce a NPE or 
potentially work just fine and this IoC quirk goes undetected, which is a 
ticking time bomb. Perhaps this method should be renamed to 
eagerLoadUnordered() or better yet removed entirely, and another way of 
ordering these should be introduced.

An illustrative example is given below with two eagerloaded services 
(SiteInitialise sets up database connections and the connection pool, 
ImageService loads a cache of image data, so implicitly ImageService requires 
SiteInitialise to be loaded first).

//Example: The shell of the eagerloaded ImageService service
public class ImageService {

                 /** Cache to hold thumbnail images */
                 private static ConcurrentHashMap<Integer, Thumbnail>
imageCache_ = new ConcurrentHashMap<Integer, Thumbnail>();

 
                 public void preloadImageCache() {
                                 DbConnection connection = null;
                                 try {
                        //This can potentially  turn into a Null Pointer 
Exception as the startup order is arbitrary
                                    connection = 
DatabaseConnection.getReadConnection();
                                                 //database query
                                 } catch (Exception e) {
                                                 //handle exception
                                 }
                 }


                 public static ImageService build() {
                                 return new ImageService();
                 }

                 public ImageService() {
                                 preloadImageCache();
                 }
 }

//Workaround: adding a dependency on the other eagerloaded service will solve
it, but this is not a practical solution if there are many of these services
public class ImageService {

                 /** Cache to hold thumbnail images */
                 private static ConcurrentHashMap<Integer, Thumbnail>
imageCache_ = new ConcurrentHashMap<Integer, Thumbnail>();

 
                 public void preloadImageCache() {
                                 DbConnection connection = null;
                                 try {
                                                 connection =
DatabaseConnection.getReadConnection();
                                                 //database query
                                 } catch (Exception e) {
                                                 //handle exception
                                 }
                 }


                 public static ImageService build(SiteInitialise
siteInitialise) {
                                 return new ImageService(siteInitialise);
                 }

                 public ImageService(SiteInitialise siteInitialise) {
                                 if(siteInitialise.isConnectionOk())
                                                 preloadImageCache();
                 }
 }




  was:
It is mentioned in the documentation that the order in which services are 
created is not defined when using eagerLoad().

You can get into serious trouble If ordering of eagerloaded services is 
important (and it often is) by using :
binder.bind(ImageService.class).eagerLoad();

It can produce a NPE or work just fine and go undetected, so is a ticking time 
bomb. Perhaps this method should be renamed to eagerLoadUnordered() or removed 
entirely, and a way of ordering these would be great to have. An illustrative 
example is given below with two eagerloaded services (SiteInitialise sets up 
database connections and the connection pool, ImageService loads a cache of 
image data, so implicitly requires SiteInitialise to be loaded first).

//Example: The shell of the eagerloaded ImageService service
public class ImageService {

                 /** Cache to hold thumbnail images */
                 private static ConcurrentHashMap<Integer, Thumbnail>
imageCache_ = new ConcurrentHashMap<Integer, Thumbnail>();

 
                 public void preloadImageCache() {
                                 DbConnection connection = null;
                                 try {
                        //This can potentially  turn into a Null Pointer 
Exception as the startup order is arbitrary
                                    connection = 
DatabaseConnection.getReadConnection();
                                                 //database query
                                 } catch (Exception e) {
                                                 //handle exception
                                 }
                 }


                 public static ImageService build() {
                                 return new ImageService();
                 }

                 public ImageService() {
                                 preloadImageCache();
                 }
 }

//Workaround: adding a dependency on the other eagerloaded service solves
it, but this is not a practical solution if there are many of these
services
public class ImageService {

                 /** Cache to hold thumbnail images */
                 private static ConcurrentHashMap<Integer, Thumbnail>
imageCache_ = new ConcurrentHashMap<Integer, Thumbnail>();

 
                 public void preloadImageCache() {
                                 DbConnection connection = null;
                                 try {
                                                 connection =
DatabaseConnection.getReadConnection();
                                                 //database query
                                 } catch (Exception e) {
                                                 //handle exception
                                 }
                 }


                 public static ImageService build(SiteInitialise
siteInitialise) {
                                 return new ImageService(siteInitialise);
                 }

                 public ImageService(SiteInitialise siteInitialise) {
                                 if(siteInitialise.isConnectionOk())
                                                 preloadImageCache();
                 }
 }





> Tapestry IoC should provide an OrderedConfiguration for EagerLoaded services
> ----------------------------------------------------------------------------
>
>                 Key: TAP5-795
>                 URL: https://issues.apache.org/jira/browse/TAP5-795
>             Project: Tapestry 5
>          Issue Type: Improvement
>          Components: tapestry-ioc
>    Affects Versions: 5.1
>         Environment: Any
>            Reporter: Peter Stavrinides
>            Priority: Critical
>
> It is mentioned in the documentation that the order in which services are 
> created is not defined when using eagerLoad(). This is somewhat counter 
> productive in a sense as you can get into serious trouble If ordering of 
> eagerloaded services is important (and very often it is, as the very concept 
> implies ordering and availability before other services), yet ordering is 
> ignored for eagerloaded services? 
> So by using :
> binder.bind(SomeService.class).eagerLoad(); you can produce a NPE or 
> potentially work just fine and this IoC quirk goes undetected, which is a 
> ticking time bomb. Perhaps this method should be renamed to 
> eagerLoadUnordered() or better yet removed entirely, and another way of 
> ordering these should be introduced.
> An illustrative example is given below with two eagerloaded services 
> (SiteInitialise sets up database connections and the connection pool, 
> ImageService loads a cache of image data, so implicitly ImageService requires 
> SiteInitialise to be loaded first).
> //Example: The shell of the eagerloaded ImageService service
> public class ImageService {
>                  /** Cache to hold thumbnail images */
>                  private static ConcurrentHashMap<Integer, Thumbnail>
> imageCache_ = new ConcurrentHashMap<Integer, Thumbnail>();
>  
>                  public void preloadImageCache() {
>                                  DbConnection connection = null;
>                                  try {
>                         //This can potentially  turn into a Null Pointer 
> Exception as the startup order is arbitrary
>                                     connection = 
> DatabaseConnection.getReadConnection();
>                                                  //database query
>                                  } catch (Exception e) {
>                                                  //handle exception
>                                  }
>                  }
>                  public static ImageService build() {
>                                  return new ImageService();
>                  }
>                  public ImageService() {
>                                  preloadImageCache();
>                  }
>  }
> //Workaround: adding a dependency on the other eagerloaded service will solve
> it, but this is not a practical solution if there are many of these services
> public class ImageService {
>                  /** Cache to hold thumbnail images */
>                  private static ConcurrentHashMap<Integer, Thumbnail>
> imageCache_ = new ConcurrentHashMap<Integer, Thumbnail>();
>  
>                  public void preloadImageCache() {
>                                  DbConnection connection = null;
>                                  try {
>                                                  connection =
> DatabaseConnection.getReadConnection();
>                                                  //database query
>                                  } catch (Exception e) {
>                                                  //handle exception
>                                  }
>                  }
>                  public static ImageService build(SiteInitialise
> siteInitialise) {
>                                  return new ImageService(siteInitialise);
>                  }
>                  public ImageService(SiteInitialise siteInitialise) {
>                                  if(siteInitialise.isConnectionOk())
>                                                  preloadImageCache();
>                  }
>  }

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to