Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'storageService' defined in com.mypackage.storage.springcontent.SpringContentFilesystemStorageConfig: Unsatisfied dependency expressed through method 'storageService' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.mypackage.storage.springcontent.ResourceContentStore' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
public interface ResourceContentStore extends ContentStore<Resource, String> {
}
In my opinion, the problem lies somewhere in the auto-configuration when we have these two modules simultaneously:
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-fs-boot-starter</artifactId>
<version>1.1.0.M4</version>
</dependency>
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-s3-boot-starter</artifactId>
<version>1.1.0.M4</version>
</dependency>
But I can't figure out exactly what's going on.
ContentStore
s are for associating content with Spring Data Entities and therefore you would type your ContentStore to your Entity; e.g. something like public interface MyEntityContentStore extends ContentStore<MyEntity, String>
. If you don't want to do this then you would probably be best using a Store; e.g. public interface MyStore extends Store<String>
. Which are you trying to do?
ResourceContentStore
.
ResourceContenStore
so you will need to tell it by adding two stores that extend the implementation-specific ContentStores
; i.e. FilesystemResourceContentStore extends FilesystemContentStore
and S3ResourceContentStore extends S3ContentStore
. That will have a bit of a ripple effect into your storageService bean initializor methods but SpringContentStorageService
can be typed to just ContentStore
. I believe that might work for you.
public static <T, ID extends Serializable> T newContentCopy(LockingAndVersioningRepository<T, ID> repository, T content, Consumer<T> onNewCopy) {
content = repository.lock(content);
try {
T newContent = repository.workingCopy(content);
try {
onNewCopy.accept(newContent);
return newContent;
} finally {
repository.unlock(newContent);
}
} finally {
repository.unlock(content);
}
}
unlock
someone else could then lock content and create another working copy. I am not sure that I have tested that! My assumption has always been that the lock extends across newWorkinCopy
and version
but that said, perhaps unlock should throw an error if a working copy exists.
public static <T, ID extends Serializable> T newContentCopy(LockingAndVersioningRepository<T, ID> repository, T content, Predicate<T> predicate, Consumer<T> onNewCopy) {
content = repository.lock(content);
try {
if (predicate.test(content)){
T newContent = repository.workingCopy(content);
try {
onNewCopy.accept(newContent);
} finally {
return repository.unlock(newContent);
}
}
} finally {
repository.unlock(content);
}
return null;
}```java
'return' inside 'finally' block
version
instead on newWorkingCopy
as it looks like you have no need for a real private working copy that can be edited multiple times and saved before versioning?
version
, not workingCopy
. Working copies is a construct brought over from CMIS and is meant for use cases where you have a user that will want to edit their 'word doc' many times before versioning it. Your code suggests you dont want working copies. You just want to version
save
and setContent
and because it is handled by hibernate removes the need for the pessimistic locking. It is more of an auditing thing but I mention it because it might be a better solution for you, depending on your use case.
workingCopy
doesn't set @SuccessorId, I think I have to use this method
version
can replaced with workingCopy
?