2

I followed tutorial for uploading files but I end up with the following error:

Parameter 0 of constructor in nu.pk.cv.storage.FileSystemStorageService required a bean of type 'nu.pk.cv.storage.StorageProperties' that could not be found.


Action:

Consider defining a bean of type 'nu.pk.cv.storage.StorageProperties' in your configuration

The only difference that I know that I have done is that I use @RestController instead of only @Controller And that I have my controller in another subpackage and not in the parent package. My storage classes are in nu.pk.cv.storage while my controller is in nu.pk.cv.cv.

StorageProperties

package nu.pk.cv.storage;

@ConfigurationProperties("storage")
public class StorageProperties {

    private String location = "/tmp/cv-gen";

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

}

FileSystemStorageService

package nu.pk.cv.storage;

@Service
public class FileSystemStorageService implements StorageService {

    private final Path rootLocation;

    @Autowired
    public FileSystemStorageService(StorageProperties properties) {
        this.rootLocation = Paths.get(properties.getLocation());
    }

    @Override
    public void store(MultipartFile file) {
        String filename = StringUtils.cleanPath(file.getOriginalFilename());
        try {
            if (file.isEmpty()) {
                throw new StorageException("Failed to store empty file " + filename);
            }
            if (filename.contains("..")) {
                // This is a security check
                throw new StorageException(
                        "Cannot store the file with relative path outside the current directory "
                                + filename);
            }
            try (InputStream inputStream = file.getInputStream()) {
                Files.copy(inputStream, this.rootLocation.resolve(filename),
                    StandardCopyOption.REPLACE_EXISTING);
            }
        }
        catch (IOException e) {
            throw new StorageException("Failed to store file " + filename, e);
        }
    }

    @Override
    public Stream<Path> loadAll() {
        try {
            return Files.walk(this.rootLocation, 1)
                .filter(path -> !path.equals(this.rootLocation))
                .map(this.rootLocation::relativize);
        }
        catch (IOException e) {
            throw new StorageException("Failed to read stored files", e);
        }

    }

    @Override
    public Path load(String filename) {
        return rootLocation.resolve(filename);
    }

    @Override
    public Resource loadAsResource(String filename) {
        try {
            Path file = load(filename);
            Resource resource = new UrlResource(file.toUri());
            if (resource.exists() || resource.isReadable()) {
                return resource;
            }
            else {
                throw new StorageFileNotFoundException(
                        "Could not read file: " + filename);

            }
        }
        catch (MalformedURLException e) {
            throw new StorageFileNotFoundException("Could not read file: " + filename, e);
        }
    }

    @Override
    public void deleteAll() {
        FileSystemUtils.deleteRecursively(rootLocation.toFile());
    }

    @Override
    public void init() {
        try {
            Files.createDirectories(rootLocation);
        }
        catch (IOException e) {
            throw new StorageException("Could not initialize storage", e);
        }
    }
}

My controller

package nu.pk.cv.cv;

@RestController
public class CV {
    @Autowired
    private StorageService storageService;

    @PostMapping("/api/cv/generate")
    public String generate(@RequestParam("files") MultipartFile file) {

        storageService.store(file);

        return "Mjau";
    }
}

3 Answers 3

4

According to Baeldung article you need to add also @Configuration to your class:

@Configuration
@ConfigurationProperties("storage")
public class StorageProperties
Sign up to request clarification or add additional context in comments.

Comments

2

add annotation @Configuration or @Component at StorageProperties class.

    @Configuration
    @ConfigurationProperties("storage")
    public class StorageProperties {

or

@Component
@ConfigurationProperties("storage")
public class StorageProperties {

if you receive an Error like "a bean not found or a bean of type configuration", then you have to check your @Component, @Service or @Repository annotations in the related classes.

ref: Spring blog

1 Comment

This helped me. I didn't realize I skipped adding @Component to my Handler...
0

If you want constructor injection (for example for lombok or missing setters) you must declare it with @ConstructorBinding at the type level or on the specific constructor if there are multiple.

@Configuration
@ConfigurationProperties("storage")
@ConstructorBinding
public class StorageProperties{

or

@Configuration
@ConfigurationProperties("storage")
public class StorageProperties{
  public StorageProperties(){...}

  @ConstructorBinding
  public StorageProperties(String location){this.location = location; ...}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.