Home > Software engineering >  Resourcebundles in tomcat deployment war not working as expected
Resourcebundles in tomcat deployment war not working as expected

Time:03-02

I am experiencing a strange issue related to loading of resource bundles. After some debugging, i am able to find out the cause of the issue as resource bundles are loading in expected order. But, I query is what is causing it. I have resource bundles named as below.

core_cs.properties
core_de.properties
core_en_GB.properties
core_en_US.properties
core_en.properties
core_fr.properties

When resource bundles are loaded by spring configuration, then base name should be

../core
../core_en

But, it is resulting in

../core_en
../core

Due to this, every locale is showing translated value from core_en resource bundle. In project, i am adding core.jar as dependency in my web project.

Current Behaviour.

found == META-INF/resourcebundles/core_en for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_en_GB.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_cs.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_de.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_es.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_fr.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_hu.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_it.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_nl.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_pl.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_sl.properties
found == META-INF/resourcebundles/core_en for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_en_US.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_en.properties

Expected loading should be

found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_cs.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_de.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_en.properties
found == META-INF/resourcebundles/core_en for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_en_GB.properties
found == META-INF/resourcebundles/core_en for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_en_US.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_es.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_fr.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_hu.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_it.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_nl.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_pl.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_sl.properties

I am using PathMatchingResourcePatternResolver from springframework to resolve the path from classpath configuration

    <bean id="messageSource" >
        <property name="basename" value="classpath*:/META-INF/resourcebundles/**/*.properties"/>  
    </bean>

ClasspathResourceBundleMessageSource is extending ResourceBundleMessageSource from springframework

public void setBasenames(final String... basenames) {
        List<String> basenamesList = new ArrayList<>();
        try {

            for (String basename : basenames) {
                LOGGER.info("==\t Base Name configured {}", basename);
                Resource[] resources = (new PathMatchingResourcePatternResolver()).getResources(basename);
                for (Resource resource : resources) {
                    LOGGER.info("==\t Name of resource found {}", resource.getURI());
                    String filename = resource.getURI().toString();
                    String newBasename = transformToBasename(filename);
                    if (newBasename != null && !basenamesList.contains(newBasename)) {
                        LOGGER.info("Adding resource bundle basename {}", newBasename);
                        basenamesList.add(newBasename);
                    }
                }
            }

            // Add the basenames found
            LOGGER.info("Resource bundle path:{}", basenamesList);
            String[] basenamesArray = basenamesList.toArray(new String[]{});
            super.setBasenames(basenamesArray);
        } catch (Exception ex) {
            LOGGER.error("Error setting base names", ex);
        }
    }

Another insight is that, if i build archive war locally it works. But, when archive is build by build server (jenkins), then it is not working as expected.

CodePudding user response:

I found that JarFile.entries() method from java.util.jar.JarFile is returning list of files in unsorted order. I tested it with a small program.

import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class JarFileTest {

    public static void main(String[] args) {

        File correctJarFile = new File("D:\\target\\budget.jar");
        File wrongJarFile = new File("D:\\target\\budget2.jar");
     
        try (JarFile jar = new JarFile(correctJarFile )) {
            for (Enumeration<JarEntry> entries = jar.entries(); entries.hasMoreElements(); ) {
                JarEntry entry = entries.nextElement();
                String entryPath = entry.getName();
                if (entryPath.endsWith(".properties")) {
                    System.out.println(entryPath);
                }
            }
        }catch (IOException e) {
        }
        System.out.println("\n============ 2");
        try (JarFile jar = new JarFile(wrongJarFile)) {
            for (Enumeration<JarEntry> entries = jar.entries(); entries.hasMoreElements(); ) {
                JarEntry entry = entries.nextElement();
                String entryPath = entry.getName();
                if (entryPath.endsWith(".properties")) {
                    System.out.println(entryPath);
                }
            }
        }catch (IOException e) {
        }
    }
}

Above program result in below output.

META-INF/resourcebundles/core_cs.properties
META-INF/resourcebundles/core_de.properties
META-INF/resourcebundles/core_en.properties
META-INF/resourcebundles/core_en_GB.properties
META-INF/resourcebundles/core_en_US.properties
META-INF/resourcebundles/core_fr.properties

============ 2
META-INF/resourcebundles/core_en_GB.properties
META-INF/resourcebundles/core_cs.properties
META-INF/resourcebundles/core_de.properties
META-INF/resourcebundles/core_fr.properties
META-INF/resourcebundles/core_en_US.properties
META-INF/resourcebundles/core_en.properties

This is same with Java8 Stream API

        try (JarFile jar = new JarFile(jarFile)) {
            jar.stream().filter(entry -> entry.getName().endsWith(".properties")).forEach(System.out::println);
        } catch (IOException e) {
        }
        System.out.println("\n============ 0");
        try (JarFile jar = new JarFile(jarFile2)) {
            jar.stream().filter(entry -> entry.getName().endsWith(".properties")).forEach(System.out::println);
        } catch (IOException e) {
        }

So, I have applied custom sorting to fix ordering in ZipFile as mentioned in this stackoverflow question

  • Related