Quantcast

Problem reading a resource file (migrating 2.3.29 --> 2.5.10)

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Problem reading a resource file (migrating 2.3.29 --> 2.5.10)

Heikki Hyyrö
Hi,

I decided to migrate a Struts-based application from Struts 2.3.x to
2.5.x. The application worked without problems with Struts version
2.3.29. After updating to 2.5.10, the application no longer seems to be
able to read a root-level resource file "package.properties": calling
getText("some.needed.property") results in an exception.

Since this problem did not happen with 2.3.29, I wonder if the 2.5.x
versions have introduced a fundamental change in how the resource files
are handled? I was not able to find such information in the 2.3 --> 2.5
migration guide.

The problem occurs in the constructor of a database connection manager
class that tries to retrieve database information (driver information,
database url, and so on) from package.properties. A rough sketch of the
class is something like:

public class DbConnectionManager extends ActionSupport
{
   private DbConnectionManager()
   {
     String driverNames = getText("database.drivers");  // This throws
an exception in 2.5.10, but was ok in 2.3.29.
     ...
   }
}

I suppose this problem could have something to do with the fact that
this is a singleton class that is initialized only once during the
lifetime of the application? If this is the case, then what would a
simple way to fix the problem? A related question would be: how should I
access resource files from a non-action context (e.g. read resources in
static initialization), if ActionSupport no longer permits it?

-Heikki


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Problem reading a resource file (migrating 2.3.29 --> 2.5.10)

Lukasz Lenart
2017-03-11 0:21 GMT+01:00 Heikki Hyyrö <[hidden email]>:

> Hi,
>
> I decided to migrate a Struts-based application from Struts 2.3.x to 2.5.x.
> The application worked without problems with Struts version 2.3.29. After
> updating to 2.5.10, the application no longer seems to be able to read a
> root-level resource file "package.properties": calling
> getText("some.needed.property") results in an exception.
>
> Since this problem did not happen with 2.3.29, I wonder if the 2.5.x
> versions have introduced a fundamental change in how the resource files are
> handled? I was not able to find such information in the 2.3 --> 2.5
> migration guide.
>
> The problem occurs in the constructor of a database connection manager class
> that tries to retrieve database information (driver information, database
> url, and so on) from package.properties. A rough sketch of the class is
> something like:
>
> public class DbConnectionManager extends ActionSupport
> {
>   private DbConnectionManager()
>   {
>     String driverNames = getText("database.drivers");  // This throws an
> exception in 2.5.10, but was ok in 2.3.29.
>     ...
>   }
> }
>
> I suppose this problem could have something to do with the fact that this is
> a singleton class that is initialized only once during the lifetime of the
> application? If this is the case, then what would a simple way to fix the
> problem? A related question would be: how should I access resource files
> from a non-action context (e.g. read resources in static initialization), if
> ActionSupport no longer permits it?

This is do the changes in ActionSupport's dependencies, you must
inject them first to have access to resource bundles.

Instead your approach with singleton you can use something like this

public class DbConnectionManager {

  public DbConnectionManager(@Inject TextProvider textProvider) {
    String driverNames = textProvider.getText("database.drivers");
    ...
  }
}

and then

public class MyAction extends ActionSupport {

  public String execute() {
    DbConnectionManager mgr = container.inject(DbConnectionManager.class)
    ....
  }
}

but perhaps the best option would be to disconnect your DAO layer from
Web layer, you have coupled two different layers which is a "bad
design" ™


Regards
--
Łukasz
+ 48 606 323 122 http://www.lenart.org.pl/

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Problem reading a resource file (migrating 2.3.29 --> 2.5.10)

Heikki Hyyrö
11.03.2017, 09:20, Lukasz Lenart kirjoitti:

> This is do the changes in ActionSupport's dependencies, you must
> inject them first to have access to resource bundles.
>
> Instead your approach with singleton you can use something like this
>
> public class DbConnectionManager {
>
>    public DbConnectionManager(@Inject TextProvider textProvider) {
>      String driverNames = textProvider.getText("database.drivers");
>      ...
>    }
> }
>
> and then
>
> public class MyAction extends ActionSupport {
>
>    public String execute() {
>      DbConnectionManager mgr = container.inject(DbConnectionManager.class)
>      ....
>    }
> }
>
> but perhaps the best option would be to disconnect your DAO layer from
> Web layer, you have coupled two different layers which is a "bad
> design" ™
Thanks, I will have a look at this.

I now that the particular example was a bit of a hack.
DBConnectionManager inherited ActionSupport only for the sole purpose of
getting easy access to the resource files (just rely on the framework to
find it; no need to hard code any path or filename). Changing this is
not such a big deal; something like
DbConnectionManager.class.getResourceAsStream("package.properties")
should work.

A related question is how to access resources from a static context. For
example if I have an Enum whose constants are based on strings defined
in the resource files, what would be a proper way to access them? I am
thinking of something like:

public Enum Event
{
     SOME_EVENT(0, "header.some_event"),
     ANOTHER_EVENT(1, "header.another_event"),
     ...

     private final int eventId;
     private final String eventString;

     private LogEvent(int id, String description)
     {
         eventId = id;
         // How to achieve the following conversion of a generic
         // header into how its defined in the resource files?
         eventString = getText(string);
     }
}

Is there a nice way to handle this with getText, or should I again use
getResourceAsStream or some other non-Struts facility?

-Heikki

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Problem reading a resource file (migrating 2.3.29 --> 2.5.10)

Lukasz Lenart
2017-03-12 0:30 GMT+01:00 Heikki Hyyrö <[hidden email]>:

> I now that the particular example was a bit of a hack. DBConnectionManager
> inherited ActionSupport only for the sole purpose of getting easy access to
> the resource files (just rely on the framework to find it; no need to hard
> code any path or filename). Changing this is not such a big deal; something
> like DbConnectionManager.class.getResourceAsStream("package.properties")
> should work.
>
> A related question is how to access resources from a static context. For
> example if I have an Enum whose constants are based on strings defined in
> the resource files, what would be a proper way to access them? I am thinking
> of something like:
>
> public Enum Event
> {
>     SOME_EVENT(0, "header.some_event"),
>     ANOTHER_EVENT(1, "header.another_event"),
>     ...
>
>     private final int eventId;
>     private final String eventString;
>
>     private LogEvent(int id, String description)
>     {
>         eventId = id;
>         // How to achieve the following conversion of a generic
>         // header into how its defined in the resource files?
>         eventString = getText(string);
>     }
> }
>
> Is there a nice way to handle this with getText, or should I again use
> getResourceAsStream or some other non-Struts facility?

In theory you can use LocalizedTextUtil and its findText() methods but
right now I'm working on converting this static util class into a bean
(because of many reasons) so you will have the same problem as with
DbConnectionManager at some point.

Another option is to use ActionContext but that can be only used in a
Enum's method and when that method will be called from within a Struts
action.

ActionContext.getContext().getContainer().getInstance(TextProvider.class).getText(...)


Regards
--
Łukasz
+ 48 606 323 122 http://www.lenart.org.pl/

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Loading...