Spring-Boot Resource Not Found when using executeable Jar

后端 未结 3 1064
情话喂你
情话喂你 2020-12-19 09:21

again I face a strange issue and hope someone here can help.

I have a spring boot backend module, what works in eclipse well and application is executeable when sta

相关标签:
3条回答
  • 2020-12-19 09:57

    I encountered this limitation too and created this library to overcome the issue: spring-boot-jar-resources

    It basically allows you to register a custom ResourceLoader with Spring Boot that extracts the classpath resources from the JAR as needed, transparently:

    new SpringApplicationBuilder()
            .sources(Application.class)
            .resourceLoader(new JarResourceLoader())
            .run(args);
    

    With that ResourceLoader you can do resource.getFile() on any classpath resource.

    0 讨论(0)
  • 2020-12-19 10:00

    Now I needed to find xmlFiles into a resource folder from a JAR and facing similar problems described here already. I would like to share my findings and how I got it work, maybe it is helpful.

    In a jar I have "db-input" folder under src/main/resources with any number for xml-Files for DB-Input. My application is Spring-Based:

    @Component
    public class DatabaseInitializer implements InitializingBean {
        @Autowired DomainConfigurationRepository repository;
        @Autowired MarshallerService marshallerService;
        @Autowired ApplicationContext context;
    
        @Override
        public void afterPropertiesSet() throws Exception {
            final Resource[] resources = context.getResources("classpath*:db-input/*");
            final Set<String> filePaths = findInputFileNames(resources);
            final Set<DomainConfiguration> configurations = createConfigurations(filePaths);
            repository.save(configurations);
        }
    
        private  Set<DomainConfiguration> createConfigurations(final Set<String> filePaths) throws Exception {
            final Set<DomainConfiguration> configurations = new HashSet<>();
            for(final String path : filePaths){
                final Resource resource = context.getResource(path);
                final DomainConfigurationXO xoConfiguration = marshallerService.unmarshal(resource.getInputStream());
                final DomainConfiguration configuration = PopulationUtils.getPopulatedConfiguration(xoConfiguration);
                configurations.add(configuration);
            }
            return configurations;
        }
    
        public Set<String> findInputFileNames(final Resource[] inputDirectoryResources) throws IOException {
            return Arrays.stream(inputDirectoryResources)
                    .map(resource -> extractURI(resource))
                    .collect(Collectors.toSet());
        }
    
        private String extractURI(Resource resource){
            try {
                return resource.getURI().toString();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-19 10:03

    Okay, already I found the real problem and the solution.

    First, the application use the correct path to the csv files, but there is another issue when using an executable jar what I found under following link. Stackoverflow-Link

    Before I come to issue with executable jar I used following solution for getting CSV-File (Issue is getFile()):

    final List<String> resourceLines = FileReadUtils.readLines(specialisationResource.getFile());
    for (final String line : resourceLines) {
      data.add(getNewTransientSpecialisation(line));
    }
    

    But in executeable jar I cant use my resource as file, I need to use it as stream, see provided link above. So I needed to change my code. If you prefer using native java, you can do follows:

    final InputStream inputStream = specialisationResource.getInputStream();
    final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
    
    String line;
    while ((line = bufferedReader.readLine()) != null) {
        data.add(getNewTransientSpecialisation(line));
    }
    

    I prefer using frameworks and use apache commons like follows:

    final List<String> resourceLines = IOUtils.readLines(specialisationResource.getInputStream());
    for (final String line : resourceLines) {
        data.add(getNewTransientSpecialisation(line));
    }
    

    So just remember, don't use File() for getting resource, always use stream do avoid that issue from beginning :-)

    Hope that helps someone.

    0 讨论(0)
自定义标题
段落格式
字体
字号
代码语言
提交回复
热议问题