0

i have created springboot project which gives fat-jar. i want to push external xml file in runtime into it.i want to place that xml file into spring-boot-tomcat container. tried many ways to do it (@import, --spring.config.location,etc) those ways didn't work out for me.

That xml file is ApplicationInsight.xml, which is used to post telemetry from our application to Azure portal.

Highly appreciate any help.

Muni
  • 53
  • 2
  • 12
  • How are you deploying and running your application (OS, Cloud platform, etc)? – Pytry Dec 14 '17 at 20:03
  • Here is the full problem description.https://github.com/Microsoft/ApplicationInsights-Java/issues/472 – Muni Dec 15 '17 at 06:33

1 Answers1

0

Based on the GitHJub issue, I think part of the problem is how you are passing JVM parameters, and how you are using "spring.config.location".

I am not familiar with Azure Insights really, but if I understand correctly, it is trying to load the ApplicationInsights.xml file to configure itself, and it's doing this automatically. So you really can't set it up in the WebConfigurerAdapter as I previously suggested because it has already initialized itself before that, correct? I left that part in anyways, but I get that it needs to be loaded sooner so I provided a few additional ways to add the file to the classpath ASAP.

New Stuff

First take a look at this line you had originally posted ala GitHub:

java -jar build/libs/file-gateway.jar --spring.config.location=classpath:/apps/conf/ApplicationInsight.xml 

Instead the value should be just a folder path, without "classpath" of "file" prefix. Also, try using '-D' instead of '--'.

java -jar build/libs/file-gateway.jar -Dspring.config.location=/apps/conf/

The property is supposed to either refer to a directory containing auto configuration property files for Spring Boot. It can also work for referring to a specific "application.properties|yml" file.

With that, my previous suggestion may work for you.

Old Suggestion

If you require a unique way for loading resources, you can add a resource handler to your application.

@Configuration
@EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter {

    @Value("${telemetry.folder}")
    private String telemetryFolder;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry
          .addResourceLocations(telemetryFolder); 
    }
}

And/or you could load it with apache IO:

@Value("${telemetry.file}")
private String telemetryFile;

@Autowired
private ResourceLoader resourceLoader;

public String telemtryXml(){

    return org.apache.commons.io.IOUtils.toString(resourceLoader.getResource(telemtryFile).getInputStream());
}

But this will only work if the api you are using doesn't need to be initialized much earlier.

More New Stuff

In your last post on the GitHub issue, you tried this:

java -jar build/libs/file-gateway.jar -applicationinsights.configurationDirectory="/apps/conf/"

Instead, try adding the property as a jvm parameter like this:

java -jar build/libs/file-gateway.jar -Dapplicationinsights.configurationDirectory=/apps/conf/

Notice that I added a capital 'D' character after the, and I removed the quotes from the path.

Other ways to add the file to classpath are.

  1. Add the directory to the JVM classpath.

    java -cp "build/libs/file-gateway.jar:/apps/conf/*" your.package.MainSpringBootApplication

This requires that you specify the main class which is (commonly) annotated with '@SpringBootApplication' and contains the main method. You do not execute the jar like before, but you do still add it to the classpath.

  1. Forget about SpringBoot, and go back to your roots as a JEE developer. Add a "context.xml" for your app under the "src/main/resources/META-INF" folder, or "src/main/webapp/META-INF". I prefer the later if I'm building an executable war file, and the former for jars.

Example context.xml:

<?xml version='1.0' encoding='utf-8'?>
<!-- path should be the context-path of you application.
<Context path="/">
  <Resources className="org.apache.catalina.webresources.StandardRoot">
    <PreResources base="/apps/conf"
                  className="org.apache.catalina.webresources.DirResourceSet"
                  internalPath="/"
                  webAppMount="/WEB-INF/classes"/>
  </Resources>
</Context>

You can also use JVM parameters with EL.

So if you execute the jar with this:

java -jar build/libs/file-gateway.jar -Dapplicationinsights.configurationDirectory=/apps/conf/

You could set the resources base with this:

<!--snip -->
<PreResources base="${applicationinsights.configurationDirectory}" 
<!--snip -->

Hope that helps:)

Pytry
  • 6,044
  • 2
  • 37
  • 56
  • i have tried the above solution , but it didn't work out as spring resource directly reads that xml file but not into embedded-tomcat container – Muni Dec 15 '17 at 06:43
  • Ah ... I see. Let me update my answer to be more useful. – Pytry Dec 15 '17 at 16:42
  • Thank you for all detailed description. i have tried all the above old suggestion, New Stuff and More New stuffs. Nothing worked out for me , also tried to have context.xml in classpath which will read conf Dir. Those didn't help me too bcz spring resource reads those files rather than tomcat container . Can you please let me know any way to push xml file directly to embedded tomcat during startup externally ? Or set a gradle file in such a way embedded tomcat will take external conf files under it's lib location . i need to place a file in embedded-tomcat lib folder – Muni Dec 18 '17 at 09:31
  • Can you provide a sample project on GitHub that reproduces the problem? Be sure to include a details on exactly how you are deploying, running, and testing the applicarion. FYI: if the file is in the JVM classpath, then it will be available to the embedded Tomcat and subsequently to Spring Boot. One more approach could be to define a basedir (acts like catalina.base) in application.properties, which allow for an external lib folder. And there are also Spring Boot factories you could add. And of course, you could also write a bash or cmd script to just place the file inside of the jar on start. – Pytry Dec 20 '17 at 04:15
  • reproducing problem is simple, small spring boot project which reads a.xml file from src/main/resource. Finally it will generate one fat jar. now when i run the jar with embedded tomcat , i wanna place a xml file into it's container. Also i have tried to modify the jar with shell scripts all ends up in corrupted jar exception . If you find any please let me know – Muni Dec 29 '17 at 08:47
  • Hey, I got some free time sort of. Can you provide a sample project or just a sample ApplicationInsight.xml file? – Pytry Jan 12 '18 at 15:33