简体   繁体   中英

Spring, copy files during application startup

I have a Spring web application, I need to copy contents of one file to another file when the application starts up.

@Component
public class BootStartUp implements ApplicationListener<ContextRefreshedEvent> {

@Override
public void onApplicationEvent(final ContextRefreshedEvent event) {

  File sourceFile = new File(getClass().getClassLoader()
  .getResource("app_dev.json").getFile()); // Present in src/main/resources folder

  // Getting null pointer exception here
  File destFile = new File(getClass().getClassLoader()
  .getResource("AppConfig.json").getFile());  // Present in src/main/webapp folder
}

So basically i'm trying copy few properties from a file which is resources to a file in webapp folder which is used by the UI files when the application loads .

src/main/* is something that exists only in the source code usually, and not during the runtime.

Spring is a runtime-only framework, so when it loads, the artifact (WAR in this case) is already built and packaged, so its kind of too late to rely on src/main/* stuff

WAR has a well-defined layout, so first of all, I suggest to think in terms of "WAR" layout and check the paths. Just open up the prepared WAR with any tool that can read ZIP archive (Like WinRAR) and explore.

If you're running the stuff from IDE, in some cases, the src/main/resources folder may even exist and be accessible from the classpath, but in reality (real production deployment) it won't be there.

Another point I would like to emphasize here is that once WAR is packaged and deployed it probably should be considered a Read-Only artifact, which means that probably its not a good idea to copy files inside the WAR internally during the runtime.

Usually, web containers (Tomcat, Jetty, etc.) unpack the WAR in some kind of temp directory and load from the there, and you will never know the path to this directory, it always changes in Runtime.

So, assuming, UI files, are just a part of your application and there are some configuration properties that should be addressed, there are different approaches:

  1. Create some dynamic endpoint on server (Servlet for example) that upon request will dynamically return the configuration it needs, then a browser will just call the servlet and will get the result. In such an approach (just like in yours, the artifact you create still depends on an environment you run which is not that good)

  2. Keep configuration properties externally (in a filesystem or even, for much more advanced cases, use some configuration server like Consul, etc.d, spring-cloud-config, whatever) and keep your WAR environment independent. This is to complement the first approach but eliminate the dependency on the environment

To read file from webapp directory use ResourceLoder .

import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;

@Component
public class StartupHousekeeper implements ResourceLoaderAware {

    private ResourceLoader resourceLoader;

    @EventListener(ContextRefreshedEvent.class)
    public void contextRefreshedEvent() {
        try {

        // Read file from src/main/resources folder
        File sourceFile = new File(getClass().getClassLoader()
                .getResource("app_dev.json").getFile());  

        // Read file from src/main/webapp folder
        Resource resource = resourceLoader.getResource("file:webapp/AppConfig.json");
        File file=  resource.getFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM