Struts2 internationalization using a database - java

We have a rather large application, with a great deal of dynamic content. Is there anyway to force struts to use a database for the i18n lookups, instead of properties files?
I'd be open for other ways to solve this as well, if anyone has ever done i18n with dynamic content.

I don't know of an easy plug-and-play solution for this, so you will probably have to implement it yourself -- plan on spending quite a bit of time just coming to grips with how the localization features of struts 2 (and XWork) are implemented. The key will probably be to provide your own implementation of com.opensymphony.xwork2.TextProvider (and tell struts to use it by providing a <bean> tag in struts.xml). I can think of at least two ways of fitting this into the overall architecture:
Have your TextProvider implementation access the database directly. In the spirit of YAGNI, this is probably the best way to start (you can always refactor later, if necessary).
Alternatively, you could place the database code into an implementation of Java's ResourceBundle interface, which is what XWork uses internally. To me this sounds like an even more design-heavy approach, but on the plus side there are some articles around describing how to do this.

No, there is no built-in way to have Struts2 load localized content from a database. You would need to write that yourself.
What are your requirements? Do you need for users to be able to dynamically change field prompts, error messages, etc.?

You may be able to do something like that by building a custom interceptor. You could have the interceptor read all the key value pairs from your database and inject them into the value stack. The only thing I am not sure about, not really having messed with i18n with struts before, is if the i18n stuff pulls that information from the value stack. If not, I am not sure if maybe you could do something else in the interceptor to load up the information.
Building a custom interceptor is not too terribly complicated. There are plenty of tutorial sites out there, including (brace for self promotion here) my blog: http://ddubbya.blogspot.com/2011/01/creating-custom-struts2-interceptors.html.

Use properties files just for static content, like labels, messages etc.
For dynamic content start with a database table that includes a language-code-id for every language you want to use. All the dynamic content entries that are already translated go with their respective language-code-id added to their primary key. If a translation is missing, you can program your application to fall back to your default language in order to make things easier until the right translation is present.
Let your users provide their contributions in the language they like and store it with the appropriate language-id. Someone should provide the translation to the other languages in order to make the contribution complete.
...
PRIMARY KEY (`subject_id`,`language_id`),
...

Related

Getting database value to display it on JSP [duplicate]

We have a rather large application, with a great deal of dynamic content. Is there anyway to force struts to use a database for the i18n lookups, instead of properties files?
I'd be open for other ways to solve this as well, if anyone has ever done i18n with dynamic content.
I don't know of an easy plug-and-play solution for this, so you will probably have to implement it yourself -- plan on spending quite a bit of time just coming to grips with how the localization features of struts 2 (and XWork) are implemented. The key will probably be to provide your own implementation of com.opensymphony.xwork2.TextProvider (and tell struts to use it by providing a <bean> tag in struts.xml). I can think of at least two ways of fitting this into the overall architecture:
Have your TextProvider implementation access the database directly. In the spirit of YAGNI, this is probably the best way to start (you can always refactor later, if necessary).
Alternatively, you could place the database code into an implementation of Java's ResourceBundle interface, which is what XWork uses internally. To me this sounds like an even more design-heavy approach, but on the plus side there are some articles around describing how to do this.
No, there is no built-in way to have Struts2 load localized content from a database. You would need to write that yourself.
What are your requirements? Do you need for users to be able to dynamically change field prompts, error messages, etc.?
You may be able to do something like that by building a custom interceptor. You could have the interceptor read all the key value pairs from your database and inject them into the value stack. The only thing I am not sure about, not really having messed with i18n with struts before, is if the i18n stuff pulls that information from the value stack. If not, I am not sure if maybe you could do something else in the interceptor to load up the information.
Building a custom interceptor is not too terribly complicated. There are plenty of tutorial sites out there, including (brace for self promotion here) my blog: http://ddubbya.blogspot.com/2011/01/creating-custom-struts2-interceptors.html.
Use properties files just for static content, like labels, messages etc.
For dynamic content start with a database table that includes a language-code-id for every language you want to use. All the dynamic content entries that are already translated go with their respective language-code-id added to their primary key. If a translation is missing, you can program your application to fall back to your default language in order to make things easier until the right translation is present.
Let your users provide their contributions in the language they like and store it with the appropriate language-id. Someone should provide the translation to the other languages in order to make the contribution complete.
...
PRIMARY KEY (`subject_id`,`language_id`),
...

Best way of adding id's to html elements in GWT

I'm rather unexperienced in GWT, and I have large codebase with working project in this technology. My task refers to assigning id's to html elements witch will be used in automatic testing. We can't use some dynamically assigned id's because in automatic test we have to specify exact values of id's. My way for now was to use method ensureDebug(id), written by hand in code for specific elements.
I think that doing it this way mean that code will be more spaghetti-like, with mixed ensureDebug(id) methods usages there and here. I was thinking if there is any way of doing it that will be more manageable and cleaner than current. Is is maybe possible to use AOP? (I have never used AOP, so I don't know if it is any good idea, or possible in GWT) Or maybe other way than using ensureDebug?
You also can set the IDs for HTML elements like
element.setId("myId");
But this is as much spaghetti like as your approach adding the IDs in the code.
Another possibility would be to use an UiBinder and set the id there. With this approach you have all your ui elements of one view, which should have an id, at one place. With bootstrap for example it would look like this:
<b:TextBox ui:field="searchTextBox" b:id="search-text-box"/>
Like this you can access the field in your view-class via searchTextBox and the id search-text-boxis added to the HTML element (which you could also use for styling etc.)
We have faced same issue for our project while adding test automation. As per my knowledge unfortunately GWT doesn't support anything like AOP yet. So we have to follow any of the spaghetti-like approach only from one mentioned above by #mxlse or the one you are already following.
Based on my experience I can recommend you to create separate constant/property at client or server end. Use this file to save all your id's which you can share latter on with test team as well.

Decorating a multi-client webapp

I have a web-app in Java, Spring, Struts 2 and Hibernate, that servers multiple clients. Each client with multiple users. To create a personal feel for each client, i would like to customize the header for each client.
I'm using sitemesh as decorator, and am looking for tips or examples or someone who can point me in the right direction as to how to acomplish this in the best practice.
What would you think? Should i just code it direct in the header.jsp? Extracting the info about the logged in user and from that create a custom header by code? Or is there a more clever solution out there?
Thanks!
Update:
To further clearify what i want:
Different properties-files for each client is not an option. We are looking at potentionally hundreds of clients. It needs to be database-driven. But thats the easy part. There is no problem storing the information in db and extracting it when needed.
What im trying to figure out is if there is some sort of standard way of doing this. Some sort of filter or Action that is run before the sitemesh decorator that will provide the decorator with the correct info?
Struts2 provides application scope, for variables which are global to the application.
Load all the customer specific strings into #application scope (I would use spring to do this when the application starts up). From there referencing the strings would be pretty obvious: #application.greeting I don't like the idea of using an interceptor because there is nothing to intercept. I would say for what you are doing application scope is the perfect place. If it is a single client system I can see no reason why anything would be stored in application scope.
Aside: Tiles uses a different template paradigm than site mesh, and they have slightly different purposes. As such the two can be complimentary. Tiles relying on XML definitions can have it's definitions stored in a DB and is definitely less computationally intensive, however where there is interplay between different UI components... or disparate elements appearing on the page you need to use sitemesh. So for basic template needs tiles does everything and is quite easy to understand but say you wanted to make add a certain widget in the middle of the page which relies on JS which needs to be added to the header it would be tricky to do this in Tiles (although the obvious solution is to just roll the JS functionality into one JS file for all possible uses in a particular part of the site).
Asside 2: By using a view technology such as velocity or freemarker in conjunction with tiles it is conceivable to move the entire view layer into a database. I just thought I would mention that as for some maintenance issues that could be extremely beneficial.
Sitemesh makes it's decisions about what decoration to use based upon the requested URL string, so unless you have a reference to the client in every url - either as part of the main url string or as a known parameter, then Sitemesh out of the box is not going to help.
This leaves a few possibilities to achieve what you want;
1) Write a filter that runs before Sitemesh that adds, for example, "&clientId="xx" to every incoming request.
2) Dive into the source code for Sitemesh & look for where Sitemesh finally makes it's decision about which decorators to use and override it. I've never tried this so I don't know how practical this might be.
3) Make the style sheet definition in your jsp pages an OGNL expression and provide that information in a base action class that all your actions extend. In this way you end up with (potentially) a different CSS file for each client and you provide your customisation via CSS.
Hope that this helps.

Is there a dbunit-like framework that doesn't suck for java/scala?

I was thinking of making a new, light-weight database population framework. I absolutely hate dbunit. Before I do, I want to know if someone already did it.
Things i dislike about dbunit:
1) The simplest format to write and get started is deprecated. They want you to use formats that are bloated. Some even require xml schemas. Yeah, whatever.
2) They populate rows not in the order you write them, but in the order tables are defined in the xml file. This is really bad because you can't order your data in such a way that foreign key constraints won't cause problems. This just forces you to go through the hassle of turning them off altogether.
This also wastes time and bloats up your junit base classes to include code to disable the foreign key constraints. You will probably have to test for the database type (hsqldb, etc.) and disable them in database-specific ways. This is way bad.
It could be better if dbunit helped in disabling foreign key constraints as part of their framework automatically, but they don't do this. They do keep track of dialects... so why not use them for this? Ultimately, all of this does is force the programmer to waste time and not get up and testing quickly.
3) XML is a pain to write. I don't need to say more about this. They also offer so many ways to do it, that I think it just complicates matters. Just offer one really solid way and be done with it.
4) When your data gets large, keeping track of the ids and their consistent/correct relationships is a royal pain.
Also, if you don't work on a project for a month, how are you to remember that user_id 1 was an admin, user_id 2 was a business user, user_id 3 was an engineer and user_id 4 was something else? Going back to check this is wasting more time. There should be a meaningful way to retrieve it other than an arbitrary number.
5) It's slow. I've found that unless hsqldb is used, it is painfully slow. It doesn't have to be. There are also numerous ways to mess up its configuration as it is not easy to do "out of the box". There is a hump that you must go through to get it working right. All this does is encourage people to not use it, or be pissed of when they do start to use it.
6) Some values tend to repeat a lot, likes dates. It'd be nice to specify defaults, or even have the framework put defaults in automatically, even without you telling it to put defaults in there. That way you can create objects just with the values you want, and leave the rest off. This sure beats specifying every nook and cranny of a column if it's not required.
7) Probably the most annoying thing is that the first entry must include ALL the values - even null placeholders - or future rows won't pick the columns that you actually specified.
DBunit doesn't have a sensible default for translating [NULL] to a real null value either. You have to manually add it. Tell me, who hasn't done this with dbunit? Everyone has. It shouldn't be like this!
What this means is that if you have a polymorphic object, you must declare all the foreign keys to the joining tables of each subclass in the first row, even though they are null. If you do a table for all subclasses pattern, you still have to specify all the fields on the first row. This is just awful.
Anything out there to satisfy me, or should I become the next framework developer of a much better database testing framework?
I'm not aware of any real alternative to DbUnit and none of the tools mentioned by #Joe are in my eyes:
Incanto: not DB agnostic
SQLUnit: a regression and unit testing harness for testing database stored procedures (that's not what DbUnit is about)
Cactus: a tool for In-container testing (I fail to see where it helps with databases)
Liquibase: a database migration tool (doesn't load/verify data)
ORMUnit: can initialize a database but that's all
JMock: doesn't compete with DbUnit at all
That being said, I've personally used DbUnit successfully several times, on small and huge projects, and I find it pretty usable, especially when using Unitils and its DbUnit module. This doesn't mean it's perfect and can't be improved but with decent tooling (either custom made or something like Unitils), using it has been a decent experience.
So let me answer some of your points:
The simplest format to write and get started is deprecated. They want you to use formats that are bloated. Some even require xml schemas. Yeah, whatever.
DbUnit supports flat or structured XML, XLS, CSV. What revolutionary format would you like to use? By the way, a DTD or schema is not mandatory when using XML. But it gives you nice things like validation and auto-completion, how is that bad? And Unitils can generate it easily for you, see Generate an XSD or DTD of the database structure.
It could be better if dbunit helped in disabling foreign key constraints as part of their framework automatically, but they don't do this. They do keep track of dialects... so why not use them for this? Ultimately, all of this does is force the programmer to waste time and not get up and testing quickly.
They are waiting for your patch.
Meanwhile, Unitils provides support to handle constraints transparently, see Disabling constraints and updating sequences.
XML is a pain to write. I don't need to say more about this. They also offer so many ways to do it, that I think it just complicates matters. Just offer one really solid way and be done with it.
I guess pain is subjective but I don't find it painful, especially when using a schema and autocompletion. What is the silver bullet you're suggesting?
When your data gets large, keeping track of the ids and their consistent/correct relationships is a royal pain.
Keep them small, that's a know best practice. You're going against a known best practice and then complain...
Also, if you don't work on a project for a month, how are you to remember that user_id 1 was an admin, user_id 2 was a business user, user_id 3 was an engineer and user_id 4 was something else? Going back to check this is wasting more time. There should be a meaningful way to retrieve it other than an arbitrary number.
Yes, task switching is counter productive. But since you're working with low level data, you have to know how they are represented, there is no magic solution unless you use a higher level API of course (but that's not the purpose of DbUnit).
It's slow. I've found that unless hsqldb is used, it is painfully slow. It doesn't have to be. There are also numerous ways to mess up its configuration as it is not easy to do "out of the box". There is a hump that you must go through to get it working right. All this does is encourage people to not use it, or be pissed of when they do start to use it.
That's inherent to databases and JDBC, not DbUnit. Use a fast database like H2 if you want things to be as fast as possible (if you have a better agnostic way to do things, I'd be glad to learn about it).
Probably the most annoying thing is that the first entry must include ALL the values - even null placeholders - or future rows won't pick the columns that you actually specified.
Not when using Unitils as mentioned in presentations like Unitils - Home - JavaPolis 2008 or Unit testing: unitils & dbmaintain.
Anything out there to satisfy me, or should I become the next framework developer of a much better database testing framework?
If you think you can make things better, maybe contribute to existing solutions. If that's not possible and if you think you can create the killer database testing framework, what can I say, do it. But don't forget, ranting is easy, coming up with solutions using your own solutions is less so.
As a DbUnit developer I'm grateful for criticism and I must partially agree with you. We are currently starting the design of the next DbUnit major release and I wish to invite you to participate both in the discussion and development.
I'm not going to answer your points as your question is not really related to DbUnit, but to DbUnit alternatives. Anyway, I just want to highlight your point 7 is completely false: you do not need to specify all the columns on first row any more, the feature is called column sensing. I'm not going to tell you why it's not enabled by default as you are surely smart enough to understand it by yourself.
I'll give scaladbtest a deep examination in the hope we can integrate their ideas.
Faced with similar concerns using DBUnit I have found this : http://dbsetup.ninja-squad.com/index.html which may address concerns. Such as instead of representing test data in separate files all DB content is contained within the java class itself.
If you use the Spring Framework (or don’t mind using it at least for testing), then Spring DBUnit is currently the best (maintained) alternative to plain DBUnit that I know and use. Quoting their website:
Spring DBUnit provides integration between the Spring testing
framework and the popular DBUnit project. It allows you to setup and
teardown database tables using simple annotations as well as checking
expected table contents once a test completes.
Spring DBUnit appears to be the ‘somewhat official’ Spring solution for DB unit testing (with DBUnit); at least the author/maintainer of the library, Phil Webb, is working at SpringSource/Pivotal.
I use DBUnit, with a few wrappers to smooth over the rough edges. A nice tool that can either complement or overlap the functionality is Jailer. It can extract subsets of data from a reference database, and store this as either DBUnit compatible XML files, or as "topologically sorted DML files", which respect the foreign key constraints.
I just released a library called JDBDT (Java Database Delta Testing) that
you may use for database setup and validation in software tests.
Have a look at http://jdbdt.org
Best,
Eduardo
You're making excellent point.
I've been working for a lot of web portals over the last years, mostly with PHP, but also some Java now and then.
And like you I don't get that after all these years framework and unittesting developers don't seem to realize how much storage handling has changed in the last decade.
It's not enough to just send create/insert/truncate statements to some database!
If you're operating at large scale you end up employing all sorts of storage backends, organized in layers to push hot content out fast. Plus on the Database front there's the issue of data partitioning. If you don't have a proper foreign key abstraction provided you will certainly go nuts when your storage setup changes. And while we're at it: fixture ordering by foreign key precedence has many pitfalls and I have yet to see a real solution for that with DBUnit.
Anyway, the point is having just a basic database storage in place for unittesting is not enough for complex storage setups, since they often fail to reproduce problems in the live environment and are a pain in the ass to maintain.
Without wanting to sound like a fanboy: one place where things are okay is ruby on rails.
That has a persistent model concept that people seem to have actually put some thought into. If you're dealing in PHP, Symfony is the place to go. It is limited via the default inclusion of Doctrine, with is also quite DB-centric, but it has clean interfaces and great extensibility and copied the rails fixture system completely. Professionally I need to stick to homebrew solutions for now, but they work okay.
Another vote for wrapping DBUnit with a modern library to improve usability and conciseness. My choice is database-rider, which makes DBUnit a breeze to use and even supports JUnit 5 as demonstrated in the following example:
#RunWith(JUnitPlatform.class)
#ExtendWith(DBUnitExtension.class)
#DBUnit(cacheConnection = true, cacheTableNames = true)
class TestInstrumentQueryService {
private ConnectionHolder connHolder = () -> EntityManagerProvider.instance("my-jta-unit").connection();
#DBRider
#DataSet("datasets/instrumentIds.yml")
void testFindInstrumentById() {
InstrumentQueryService iqs = new InstrumentQueryService(EntityManagerProvider.em());
Instrument instr = iqs.findInstrumentById(InstrumentIdType.TICKER_BBG, "AAPL");
assertEquals(100, instr.getId());
}
}
Notice how this allows leveraging (concise) YAML testing data sets seamlessly (YAML not XML, though I'm lead to believe that DBUnit actually supports those natively).
Here's a short list of a few tools in this vein (besides DBunit) that I particularly like, or find interesting. At the very least they may offer some inspiration:
Incanto
SQLunit
Cactus
Liquibase
ORMUnit
JMock
Note that none of these are really competitors to DBunit in terms of scope or feature sets. However, there are some interesting ideas there that might be worth taking a look at. Good luck!
We are writing Daleq as a wrapper around DbUnit to address some of the mentioned concerns. It allows populating a DB just within your unit test rather than relying on editing XML files.
I too had similar issues with DBUnit. Especially for using it to populate local development data and exporting data from a real database. I ran into several cases where it would export a dataset that it couldn't then import.
This inspired me to write a new library for it: https://github.com/jeffskj/phonydata
This uses a groovy DSL to define the datasets which makes for a very compact representation of the data and makes it possible to do cool things like generate random data since it's just groovy code.
The situation of DBUnit is indeed sometimes frustrating. Some of the problem are solved from Marc Philipp with dbunit-datasetbuilder, specially if you combine it with the validator, which is in a very early stage. You can see it in action at SZE.
Disclaimer: All referenced github-resources are maintained by me.
An alternative using Spring configuration and Specs2 testing can be found here
I just released a groovy DSL based framework called pedal-loader available via github. Documentation here.
It allows you to work with JPA entity level abstraction directly. Since it is a groovy script, you can use all of the groovy constructs.
To insert rows into a table backed by a JPA entity called Student, with fields (not database columns, but mapped fields) called id, name and grade, you would do something like this:
allStudents = table(Student, ['id', 'name', 'grade']) {
row 1, 'Joe', Grade.A
rowOfInterest = row 2, 'John', Grade.B
}
Grade is an enum in the Student class that is mapped to the database column (perhaps using JPA 2.1 #Convert annotation). allStudents is a list that will hold the rows and rowOfInterest is a reference to a particular row. These properties (allStudents and rowOfInterest) become available to your unit test.

Some kind of Data persistency

Basically what I need to know is this:
I have to show a drop down list of countries to my users each country also has a code associated to it. I will have to work with both the country and the code What would be the best approach:
-We (the dev.) are thinking about a table in our app database with this data, or XML file.
-Our "architect" says that is old school and that we should use constants in our app with a map that associates the country with the code
Please Help me feel smart
I agree with you that you should not hard code this or use constants. There are a few good options depending on yours needs:
Java Properties Files - If you just have a few key-value pairs to store, these are the simplest way and easy to use.
XML Storage - If you are looking for persistence and are looking at XML for storage, I would recommend looking at JAXB. It is part of Java 6 and will make your life easier than trying to use the DOM.
Database Persistence - If you have more data that is changing often, you could also look at storing it in a database. JPA is a great standard library for doing this. That is probably overkill for what you are looking for though.
Bottom line is hard coding is a thing of the past. There are lots of great ways to get data in quickly and easily without resorting to hard coding everything.
Countries rarely change, so adding them statically as code or a config file seems reasonable. If you don't use a database for anything else, don't add one just for this feature.
If you already have XML parsing in your app, use an XML file to define the data. It already solves all kinds of issues (for example if you need to add a second attribute per country or something).
If you don't use XML for anything else, I suggest to give it a try. It doesn't add much to your app. Otherwise, use a plain text file, maybe a CSV one.
The different methods have different advantages and drawbacks:
Database:
allows you to use the country data in queries
data can be changed without redeploying the app
editing the data requires you to write some sort of frontend or do it manually via some generic SQL browser
requires database access code, and some sort of caching strategy
Any country-based logic in the code can break when the DB changes, or has to be reflected in the DB
XML:
Very easy to edit
can be changed without recompiling the app, but changes have to be deployed somehow
Requires parsing code and some sort of caching strategy
Any country-based logic in the code can break when the XML changes, or has to be reflected in the XML
Code:
Easy to edit - for developers
Changes require compilation and deployment
Requires no extra technical layers
Code and country data can't get out of synch
All in all, the "code as data" solution is indeed the nicest, if the compile&deploy step for each change is acceptable to you. The other solutions create overhead and duplication of structure (or even logic) - and no, they don't magically make it "safe" to do last-minute changes "because it's not code". Code is data, and data is code.
In short your architect is wrong (Or at least he is if your paraphrase of his position is accurate). It shouldn't be in the code.
This data is not static; a country's name changes, a new one is founded, or some cease to exist.
As far as what mechanism, it doesn't necessarily matter. Just make sure you can retrieve the data easily, that you have unit tests, and that there is straightforward mechanism to update the data.
I think that "table solution" has more flexible approach:
1. You can manage data and connecting properties
2. You can work with table directly
3. You can create associated map, based on db table))
I would certainly not use them as constants in the code.
Names can change, while countries can be created, merge, disappear, etc.
If you are already using a database, adding this may make sense. For one, it ensures that the codes that may be stored with client data are valid in terms of your country code list. So if a country disappears but a client record still refers to it, the data stays valid.
Make sure that your UI loads and caches the list; no point making a query every time if you can avoid it.
By the way, correctly handling countries in an internationalized application is much more complicated than just dealing with renames. For example, if a country or part of a country declares independence, some countries will recognize it, while others do not.

Categories