WebSphere Application Server & Liberty

WebSphere Application Server & Liberty

Join this online group to communicate across IBM product users and experts by sharing advice and best practices with peers and staying up to date regarding product enhancements.

 View Only
Expand all | Collapse all

How can the external xml configuration files be made available for war/ear file during run time or in class path?

  • 1.  How can the external xml configuration files be made available for war/ear file during run time or in class path?

    Posted Mon October 19, 2020 12:10 PM

    We are using Websphere 9 application server. We want some of the configuration files such as xml and properties files in a separate directory of Websphere server and want them too see accessible by ear/war file during the run time. I heard about shared libraries approach, but it pears that only class and jar files can be used as shared libraries, but not xml and other files. Can anyone tell me an alternative solution where the external xml configuration files be made available for war/ear file during run time or in class path?



    #Support
    #SupportMigration
    #WebSphereApplicationServer(WAS)


  • 2.  RE: How can the external xml configuration files be made available for war/ear file during run time or in class path?

    Posted Mon October 19, 2020 07:48 PM

    Hi,

    You can put the location in the Naming service (JNDI registry) as a String binding and inject into your managed objects(EJBs, Servlets, etc.) and then load it from that location. If your location changes for different environments, then the application doesn't need to know because you change the location in the binding, not the application. This can be used to load specific property files or the location of a collection of property files.

    For example:

    In the WAS console, define a Naming Space Binding (select Environment->Naming->NameSpace Bindings) .

    1) Choose the scope at which you want the binding to be visible

    2) Choose the type (presumably String)

    3) Give the entry an identifier, say "propertiesLocation"

    4) Give the entry a JNDI name that will be used to look up the string (e.g. someJNDIpath/propertiesLocationPath)

    5) Provide the actual location path as the value (e.g. /tmp/propertiespath)

    Once configured in the WAS cell, you can inject it into any managed bean (EJB example below) or you call just look it up using InitialContext. You can change the path for different environments (dev, test, prod, etc.) in the configuration without having to change the application and you can define it at different scopes (Cell, Node, Cluster, Server) to make it visible to different servers or define it with different values at any of those scopes as well.

    public class StartupBean { Logger log = LoggerFactory.getLogger(StartupBean.class); // You can look it up and inject it as a resource (lookup="someJNDIpath/propertiesLocationPath") String propertiesPath; /** * */ public StartupBean() { super(); } public void intializeApplication() { log.debug("Here is my string for to use for properties I injected: "+propertiesPath); // Alternatively, instead of injection, you can use initial context to look it up. try { Context ctx= new InitialContext(); String propertiesPathLoookup = (String)ctx.lookup("someJNDIpath/propertiesLocationPath"); log.debug("Here is my stringfor to use for properties I looked up: "+propertiesPathLoookup); } catch (Exception e) { log.error("Could not lookup the propertiesPathLoookup",e); } } }

    Hope that helps



    #Support
    #SupportMigration
    #WebSphereApplicationServer(WAS)


  • 3.  RE: How can the external xml configuration files be made available for war/ear file during run time or in class path?

    Posted Tue October 20, 2020 07:00 AM

    We are using Spring. We load applicationContext.xml from web.xml using org.springframework.web.servlet.DispatcherServlet and load an external xml configuration file which contains JNDI name info from applicationContext.xml file.

    The raw code of JNDI name info is something like this:

    <bean id="test" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> <property name="url" value="jdbc:oracle:thin::1521:TEST" /> <property name="username" value="TEST" /> <property name="password" value="TEST" /> </bean>

    Could please tell me now how to proceed for the above configuration?



    #Support
    #SupportMigration
    #WebSphereApplicationServer(WAS)


  • 4.  RE: How can the external xml configuration files be made available for war/ear file during run time or in class path?

    Posted Tue October 20, 2020 12:54 PM

    I'm not a Spring user, so I can't give you the best way to load the files. The solution below is just to get the path to the file(s) you want to load from the file system. Since it requires storing it in the Naming Service and you are using Spring to configure your resources, not configuring them in the WAS separately, it may not be the solution for you.


    If you wanted to do so, then follow the instructions below to put the *path* to the external applicationContext.xml on the file system (say, "/my/path/to/external/applicationContext.xml") as the value in the String name space binding below and then inject it into DispatcherServlet or ServletContext to use when loading the file via Spring.


    It looks to me like you want to do something like this: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/support/GenericApplicationContext.html where you are loading one application context from the classpath and one from a FileSystemResource https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/io/FileSystemResource.html


    As I said though, if you are using Spring to configure your resources, I'm not sure if you would want to separately configure the name space binding in the WAS, so the solution may not be for you.



    #Support
    #SupportMigration
    #WebSphereApplicationServer(WAS)


  • 5.  RE: How can the external xml configuration files be made available for war/ear file during run time or in class path?

    Posted Tue October 20, 2020 01:31 PM

    Just a correction to the above. It does not appear to work with Cell and Node scopes (it cannot find the resource when looking up), but it does work in Server (and presumably Cluster, I can't test that) scope.



    #Support
    #SupportMigration
    #WebSphereApplicationServer(WAS)


  • 6.  RE: How can the external xml configuration files be made available for war/ear file during run time or in class path?

    Posted Tue October 20, 2020 03:07 PM

    I have tried to load some configuration files using shared library concept by putting them in Cluster scope too, but no luck. I am getting the following error. Any idea on how to proceed further. One simple question here: how can we make an external xml file that is kept under some Websphere directory available for ear/war file that is installed in Websphere?



    /opt/IBM/WebSphere/AppServer/profiles/AppSrv01/installedApps/Cell01/awdcs_war.ear/awdcs.war/WEB-INF/classes/CustomerService/DataSourceConfiguration.xml



    #Support
    #SupportMigration
    #WebSphereApplicationServer(WAS)


  • 7.  RE: How can the external xml configuration files be made available for war/ear file during run time or in class path?

    Posted Tue October 20, 2020 03:22 PM

    Sorry ..the following error is the error:


    Caused by: java.io.FileNotFoundException: /opt/IBM/WebSphere/AppServer/profiles/AppSrv01/installedApps/Cell01/awdcs_war.ear/awdcs.war/WEB-INF/classes/CustomerService/DataSourceConfiguration.xml (No such file or directory)




    #Support
    #SupportMigration
    #WebSphereApplicationServer(WAS)


  • 8.  RE: How can the external xml configuration files be made available for war/ear file during run time or in class path?

    Posted Wed October 21, 2020 01:45 PM

    I'm confused over where you want the file to be. In your example above, it appears to be in the WAR file, in which case you can just load it from the classpath like any other resource or use the Spring GenericApplicationContext I linked to above to load it using the ClassPathResource class as in the example.

    I thought you were trying to read the file from somewhere else on the file system, not packaged in the WAR or available on the classpath, in which case you need a way to tell your application where on the file system the file is located so it can load it using FileSystemResource. The solution I gave above stores that location in JNDI so you can get access to it.

    I'm not exactly sure what you are trying to accomplish. If the file you want is already packaged in the WAR file, then just load it using a ClassPathResource and the GenericApplicationContext with any other files you want to load that way (i.e. you can load more than one). If the file is not packaged in the WAR, then you can load it from the file system using the FileSystemResource provided to the GenericApplicationContext. If you wanted to do try the shared library idea (which seems uncessesary to me), you could package your files in a .jar, make it shared library, and see if you can load it from the classpath that way.



    #Support
    #SupportMigration
    #WebSphereApplicationServer(WAS)


  • 9.  RE: How can the external xml configuration files be made available for war/ear file during run time or in class path?

    Posted Wed October 21, 2020 02:59 PM

    Thanks much your patience.

    No more confusion, I will put it in detailed way...here we go:


    I have war file in which the spring configuration file applicationContext.xml is loaded by spring framework. This applicationContext.xml files in turn loads some file named DataSourceConfiguration.xml file (This file actually contains JNDI alias name which is the same JNDI name that is configured in Websphere JNDI datasource section). We don't want to package the DataSourceConfiguration.xml file as part of war file due to some reasons. So the ultimate goal is to make DataSourceConfiguration.xml file available in the classpath of the war file so that the spring configuration file applicationContext.xml that is packaged in the war can load it.

    code snippet of web.xml:


    <listener>

    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

    </listener>

    <context-param>

    <param-name>contextConfigLocation</param-name>

    <param-value>classpath:CustomerService/applicationContext.xml</param-value>

    </context-param>


    Code snippet from applicationContext.xml:


    <import resource="DataSourceConfiguration.xml"/>

    Please note that the DataSourceConfiguration.xml is not packaged as part of war file, but is should be loaded from external path( That's my requirement)


    Not only DataSourceConfiguration.xml file, we have several other files where we keep some third party system/application related info something like ip, user name etc. We load and use such files in our application. So we want to keep such files outside the war file for obvious reasons like we can change them whenever we want without touching the war file.


    I want something similar to the conf folder or module mechanism of JBOSS application server where all the files that are kept under conf folder or specific module will be available in the classpath so that war/ear can load them whenever we want. I am not interested in providing the absolute path in the war file to load the files, but rather interested in providing the relative path. Of course the only challenge I am facing in Websphere is that I am unable to tell the Websphere that "hey! Please make my external configuration files such as DataSourceConfiguration.xml etc. available for my war file that is deployed in the server so that my war file can access them whenever it wants.


    Could you please tell me now how to do that in Websphere?



    Please let me know if you need any additional information.






    #Support
    #SupportMigration
    #WebSphereApplicationServer(WAS)


  • 10.  RE: How can the external xml configuration files be made available for war/ear file during run time or in class path?

    Posted Wed October 21, 2020 04:56 PM

    Ok. Got it. Apologies for my confusion.


    Did you confirm if the problem is just that Spring can't load it's imports using a shared library or that you cannot load anything from the classpath using a shared library? Did you select "Use an isolated class loader …." when you created the shared library and bind it to your .war module?


    You can use the Class loader Viewer under Troubleshooting to confirm that the shared library is present under the war module for the application. If the library is present and you see your file path added to the classpath for the classloader, then you should be able to load resources (files) from that location via the classloader (I tested this in my standalone WAS and it works for me).



    #Support
    #SupportMigration
    #WebSphereApplicationServer(WAS)


  • 11.  RE: How can the external xml configuration files be made available for war/ear file during run time or in class path?

    Posted Wed October 21, 2020 05:45 PM

    Thanks much for your response. Here is the Class Loader View-> Search Order view of my war file.


    My shared library directory path is:

    /opt/IBM/WebSphere/CustomerService


    But application is looking at the following location:

    /opt/IBM/WebSphere/AppServer/profiles/AppSrv01/installedApps/Cell01/awdcs_war.ear/awdcs.war/WEB-INF/classes/CustomerService/DataSourceConfiguration.xml


    It is nothing to with the Spring,. Spring loads without any issue if the files is available in the classpath.


    Could you please now tell me whether I am missing something here?







    #Support
    #SupportMigration
    #WebSphereApplicationServer(WAS)


  • 12.  RE: How can the external xml configuration files be made available for war/ear file during run time or in class path?

    Posted Wed October 21, 2020 06:01 PM

    Thanks much for your response. Here is the Class Loader View-> Search Order view of my war file.


    My shared library directory path is:

    /opt/IBM/WebSphere/CustomerService


    But application is looking at the following location:

    /opt/IBM/WebSphere/AppServer/profiles/AppSrv01/installedApps/Cell01/awdcs_war.ear/awdcs.war/WEB-INF/classes/CustomerService/DataSourceConfiguration.xml


    It is nothing to with the Spring,. Spring loads without any issue if the files is available in the classpath.


    Could you please now tell me whether I am missing something here?







    #Support
    #SupportMigration
    #WebSphereApplicationServer(WAS)


  • 13.  RE: How can the external xml configuration files be made available for war/ear file during run time or in class path?

    Posted Wed October 21, 2020 06:32 PM

    Unfortunately, I cannot see that image. It says I don't have permission or it is not available any more. A few things stand out to me:


    1) Is there only the entry under the /opt/IBM/WebSphere/.../installedApps/... directory listed in all the class loaders in the Class Loader Viewer for your WAR module? There is no entry for the shared library that contains a classpath entry /opt/WebSphere/CustomerService?


    2) Is the DataSourceConfiguration.xml also packaged in the .WAR file as well as being in /opt/WebSphere/Customer Service? It looks like it is packaged in the WAR file and if so, that would need "CustomerService" prepended to the name to find it, since the classpath root is ../WEB-INF/classes in the WAR, similar to how it set for the applicationContext.xml. Your import of just "DataSourceConfiguration.xml" will not find it.


    3) There should be an entry in the class loader viewer for the /opt/WebSphere/CustomerService classpath entry in the shared library if the library is bound to the WAR file. Did you bind the WAR module to the shared library in the console ?

    If you created an shared library with an isolated class loader, there the class loader viewer will show a node for it above the module for the CompoundClassLoader for the web module (the bottom one), if not, it will be found in the CompoundClassLoader entry with the classpaths for the WAR file. Either way, there should be an entry that shows a classpath of "/opt/WebSphere/CustomerService" if you have bound the shared library to the web module



    #Support
    #SupportMigration
    #WebSphereApplicationServer(WAS)


  • 14.  RE: How can the external xml configuration files be made available for war/ear file during run time or in class path?

    Posted Wed October 21, 2020 06:33 PM

    Moving this under the thread. The reply feature is annoying.


    Unfortunately, I cannot see that image. It says I don't have permission or it is not available any more. A few things stand out to me:


    1) Is there only the entry under the /opt/IBM/WebSphere/.../installedApps/... directory listed in all the class loaders in the Class Loader Viewer for your WAR module? There is no entry for the shared library that contains a classpath entry /opt/WebSphere/CustomerService?


    2) Is the DataSourceConfiguration.xml also packaged in the .WAR file as well as being in /opt/WebSphere/Customer Service? It looks like it is packaged in the WAR file and if so, that would need "CustomerService" prepended to the name to find it, since the classpath root is ../WEB-INF/classes in the WAR, similar to how it set for the applicationContext.xml. Your import of just "DataSourceConfiguration.xml" will not find it.


    3) There should be an entry in the class loader viewer for the /opt/WebSphere/CustomerService classpath entry in the shared library if the library is bound to the WAR file. Did you bind the WAR module to the shared library in the console ?

    If you created an shared library with an isolated class loader, there the class loader viewer will show a node for it above the module for the CompoundClassLoader for the web module (the bottom one), if not, it will be found in the CompoundClassLoader entry with the classpaths for the WAR file. Either way, there should be an entry that shows a classpath of "/opt/WebSphere/CustomerService" if you have bound the shared library to the web module



    #Support
    #SupportMigration
    #WebSphereApplicationServer(WAS)


  • 15.  RE: How can the external xml configuration files be made available for war/ear file during run time or in class path?

    Posted Thu October 22, 2020 12:21 PM

    Q1) Is there only the entry under the /opt/IBM/WebSphere/.../installedApps/... directory listed in all the class loaders in the Class Loader Viewer for your WAR module? There is no entry for the shared library that contains a classpath entry /opt/WebSphere/CustomerService?


    Ans: Yes, there is an entry for /opt/WebSphere/CustomerService and that can be viewed from the class loader view.



    2) Is the DataSourceConfiguration.xml also packaged in the .WAR file as well as being in /opt/WebSphere/Customer Service? It looks like it is packaged in the WAR file and if so, that would need "CustomerService" prepended to the name to find it, since the classpath root is ../WEB-INF/classes in the WAR, similar to how it set for the applicationContext.xml. Your import of just "DataSourceConfiguration.xml" will not find it.


    Ans: Nope, DataSourceConfiguration.xml is not packaged as part of war file. It is kept in the location of shared library, just it is referenced from war file to load it.



    3) There should be an entry in the class loader viewer for the /opt/WebSphere/CustomerService classpath entry in the shared library if the library is bound to the WAR file. Did you bind the WAR module to the shared library in the console ?


    Ans: Yes, I could see the entry for /opt/WebSphere/CustomerService in class loader view.


    Since you re unable to view the screen print images, I just copied pathos of some libraries from class loader view below:


    file:/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/installedApps/Cell01/awdcs_war.ear/awdcs.war/WEB-INF/lib/spring-web-5.0.16.RELEASE.jar

    file:/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/installedApps/Cell01/awdcs_war.ear/awdcs.war/WEB-INF/lib/spring-webmvc-5.0.16.RELEASE.jar

    file:/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/installedApps/Cell01/awdcs_war.ear/awdcs.war/WEB-INF/lib/spring-xml-3.0.7.RELEASE.jar

    file:/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/installedApps/Cell01/awdcs_war.ear/awdcs.war/WEB-INF/lib/sqljdbc4-SUPPLIED.jar

    file:/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/installedApps/Cell01/awdcs_war.ear/awdcs.war/WEB-INF/lib/unijdbc-AWDCS.jar

    file:/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/installedApps/Cell01/awdcs_war.ear/awdcs.war/WEB-INF/lib/validation-api-1.1.0.Final.jar

    file:/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/installedApps/Cell01/awdcs_war.ear/awdcs.war/WEB-INF/lib/xml-apis-1.0.b2.jar

    file:/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/installedApps/Cell01/awdcs_war.ear/awdcs.war

    file:/opt/IBM/WebSphere/CustomerService


    Any idea now?



    #Support
    #SupportMigration
    #WebSphereApplicationServer(WAS)


  • 16.  RE: How can the external xml configuration files be made available for war/ear file during run time or in class path?

    Posted Thu October 22, 2020 01:12 PM

    Ok, so the applicationContext.xml is packaged in the WAR file and it contains an import for the DataSourceConfiguration.xml in a separate location?


    I'm not a Spring guy, but the docs indicate to me that it will not work because the imported file locations are expected to be relative to the location of the file doing the import. that is, in the same directory or a subdirectory. If the applicationContext.xml is in the WAR and the rest are somewhere else, I don't think it will find it.


    https://docs.spring.io/spring-framework/docs/5.3.x/reference/html/core.html#beans-factory-xml-import


    Have you tried importing with "classpath:DataSourceConfiguration.xml" to see if it works?


    I would say that if code like this works to load your file from the classpath (as a test, run it in a ServletContextListener or Servlet and see if it loads the file)


    URL urlToLoad=this.getClass().getClassLoader().getResource("DataSourceConfiguration.xml");

    String pathToFile=urlToLoadgetPath();

    String s=new String(Files.readAllBytes(Paths.get(path)));

    System.out.println(s);


    Then it is not a classpath issue, it is a Spring issue and could be caused by the rules listed in the doc about the location.




    #Support
    #SupportMigration
    #WebSphereApplicationServer(WAS)


  • 17.  RE: How can the external xml configuration files be made available for war/ear file during run time or in class path?

    Posted Thu October 22, 2020 01:40 PM

    The same code worked fine JBOSS 6 EAP(DataSourceConfiguration.xml was kept under conf directory of JBOSS, that's it, spring loaded it)and JBOSS 7.2 EAP(created a module and referenced DataSourceConfiguration.xml file from it, it worked ).


    Tried "classpath:DataSourceConfiguration.xml" and "classpath:CustomerService

    /DataSourceConfiguration.xml", no use :(


    Spring internally uses the following class and method to load the file:

    org.springframework.core.io.ClassPathResource.getInputStream()(https://github.com/spring-projects/spring-framework/blob/master/spring-core/src/main/java/org/springframework/core/io/ClassPathResource.java)


    The spring source code snippet code which loads the file is below:


    /**

    * This implementation opens an InputStream for the given class path resource.

    * #getResourceAsStream(String)

    * #getResourceAsStream(String)

    */

    public InputStream getInputStream() throws IOException {

    InputStream is;

    if (this.clazz != null) {

    is = this.clazz.getResourceAsStream(this.path);

    }

    else if (this.classLoader != null) {

    is = this.classLoader.getResourceAsStream(this.path);

    }

    else {

    is = ClassLoader.getSystemResourceAsStream(this.path);

    }

    if (is == null) {

    throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");

    }

    return is;

    }





    #Support
    #SupportMigration
    #WebSphereApplicationServer(WAS)


  • 18.  RE: How can the external xml configuration files be made available for war/ear file during run time or in class path?

    Posted Thu October 22, 2020 01:55 PM

    Well, what works on one app server may not work on another other than what is supported in the specifications.


    A few things you could try just to see if it the class paths are setup correctly:


    1) remove applicationContext.xml from the WAR and put in the same location as DataSourceConfiguration.xml. It should load from that location if the shared library is setup correctly. If this works, then the problem is what is documented in the Spring docs.

    2) Try the code I provided to load the DataSourceConfiguration.xml file outside of Spring. If that works, then the issue is with how Spring is loading it, not with the class paths you've set up.

    3) Try programmatically loading all the context files separately (not using "import") using GenericApplicationContext class as per the link I provided earlier. Use ClassPathResource for all the files you wish to load to build your context. If that works, then it is probably not loading for the reason specified in the docs.


    All of these are just tests to isolate whether the problem is in the shared library setup, the way Spring is loading the context files, or whether the docs are correct and that file needs to be in the same dir or subdir as applicationContext.xml





    #Support
    #SupportMigration
    #WebSphereApplicationServer(WAS)