You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Heikki Hyyrö <he...@uta.fi> on 2017/03/10 23:21:28 UTC

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

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: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


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

Posted by Lukasz Lenart <lu...@apache.org>.
2017-03-12 0:30 GMT+01:00 Heikki Hyyrö <he...@uta.fi>:
> 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: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


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

Posted by Heikki Hyyrö <he...@uta.fi>.
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" \u2122
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: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


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

Posted by Lukasz Lenart <lu...@apache.org>.
2017-03-11 0:21 GMT+01:00 Heikki Hyyrö <he...@uta.fi>:
> 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: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org