Giter Club home page Giter Club logo

spring-content's Introduction

Build codecov Join the chat at https://gitter.im/spring-content/Lobby

Spring Content

Cloud-Native Content Services for Spring.

Spring Content provides modules for managing content in JPA, MongoDB's GridFS, S3 or Filesystem storage. When combined with Spring Data/REST it allows content to be associated with Spring Data Entities. The Solr module provides an integration with Apache Solr for fulltext indexing and search capabilities. The Renditions module provides a pluggable renditions framework and several out-of-the-box renderers that can render stored content in several different formats.

Getting help

Having trouble with Spring Content? We'd like to help!

Reporting Issues

Spring Content uses GitHub's integrated issue tracking system to record bugs and feature requests. If you want to raise an issue, please follow the recommendations below:

  • Before you log a bug, please search the issue tracker to see if someone has already reported the problem.
  • If the issue doesn't already exist, create a new issue.
  • Please provide as much information as possible with the issue report, we like to know the version of Spring Content that you are using, as well as your Operating System and JVM version.
  • If you need to paste code, or include a stack trace use Markdown ``` escapes before and after your text.
  • If possible try to create a test-case or project that replicates the issue.

Building from Source

You don't need to build from source to use Spring Content (binaries in https://repo.maven.apache.org/maven2/), but if you want to try out the latest and greatest, Spring Content can be easily built with the maven wrapper. You also need JDK 1.8.

$ ./mvnw clean install

If you want to build with the regular mvn command, you will need Maven v3.2.1 or above.

Also see CONTRIBUTING.md if you wish to submit pull requests, and in particular please fill out the Contributor's License Agreement before your first change, however trivial.

Building reference documentation

The reference documentation can be included in the build by specifying the docs profile.

$ ./mvnw -P docs clean install 

TIP: The generated documentation is available from spring-content/target/generated-docs/refs/dev/

Guides

The https://paulcwarren.github.io/spring-content/ site contains several guides that show how to use Spring Content step-by-step:

License

Spring Content is Open Source software released under the Apache 2.0 license.

Acknowledgements

  • Spring Content uses YourKit. YourKit supports open source projects with its full-featured Java Profiler. YourKit, LLC is the creator of YourKit Java Profiler and YourKit .NET Profiler, innovative and intelligent tools for profiling Java and .NET applications.

spring-content's People

Contributors

andye2004 avatar bowl-of-petunias avatar claudia-maderthaner-infoniqa avatar davewalter avatar dependabot-preview[bot] avatar dependabot[bot] avatar gitter-badger avatar igdianov avatar jigar07 avatar juja0 avatar kreymerman avatar lakeward avatar nbalyan avatar nick-wunderdog avatar nuvitong avatar oskoss avatar paulcwarren avatar sandip-bhoi avatar tgeens avatar tomas-pritrsky avatar treehopper avatar vierbergenlars avatar vincenting avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spring-content's Issues

full customization of file content path

Dear Paul,

I am trying to use your Spring Content Filesystem api for a CMS project.

I would like to put each content in different folders depending on the corresponding site.
But the FilesystemStoreConverter receive only the Content Id and not the Entity that describes its metadata.

Of course I could query the Metadata Repository injecting it in the class in which I define the custom converter but I think that it would be better to pass to the convert method also the entity which holds the metadata, in order to give to the developer the means to create meaningful folders and filenames.

What do you think about this proposal?

Thank you very much for your work.

Best regards,
Antonio Capani

NoSuchMethodError with MongoDB and Spring Boot 2.0.6

Spring boot uses spring-data-mongodb v2.0.6 and the signature of the store function in org.springframework.data.mongodb.gridfs.GridFsTemplate class have changed from:

public GridFSFile store(InputStream content, String filename)

to:

public ObjectId store(InputStream content, String filename)

java.lang.NoSuchMethodError: org.springframework.data.mongodb.gridfs.GridFsTemplate.store(Ljava/io/InputStream;Ljava/lang/String;)Lcom/mongodb/gridfs/GridFSFile;
at internal.org.springframework.content.mongo.repository.DefaultMongoStoreImpl.setContent(DefaultMongoStoreImpl.java:54)

Stream bytea from postgresql

Hi,
We stumbled on your wonderful project while looking for ways to upload and download attachments to/from JPA based stores via streaming (instead of loading everything in memory) using spring boot. We have been evaluating spring-content and have had success streaming binary content to postgresql without loading the entire attachment in memory. So our uploads work beautifully without taking any extra memory. However, we are unable to stream content from postgresql to the rest client. The JDBC driver seems to be loading the entire contents to memory thus resulting in OutOfMemoryErrors. Are there any settings that we need to use in order to enable streaming when downloading binary content from postgresql to REST client? Would really appreciate any help/tips you can provide.

Thanks!

Question regarding elasticsearch indexing

The documentation says there's support for elasticsearch indexing of stored content on the roadmap - the code itself seems to already have elasticsearch logic in place.

What's the status on this? Would you accept help to advance this further if needed? We're currently investigating our possible approache to indexing. Since we're already using spring-content-s3 and elasticsearch, combining the 2 pieces would be logic step for us :)

Versioning strategy

Hi Paul,

Thanks for this great contribution.

I can't tell you how hard it is to find a nice, clean abstraction for managing enterprise content.

Spring Content checks all the boxes for us. In addition to it being clean and conceptually uncluttered, I like the cloud native option.

Re: versioning. Spring Content doesn't seem to support resource versioning out of the box. An obvious strategy is to simply only allow adds/appends and, perhaps, turn off the searchability/indexing for non-current versions. Also, it looks like the id is generated by Spring Content, so I assume we couldn't use that for versioning (1.0, 1.1...,). Let me know if I have that wrong.

Obviously the store would get bloated over time and that would need to be addressed by some other process.

Am I missing anything major here? Would we be fighting an uphill battle by using this framework and attempting a poor man's version of versioning ;-) ?

Custom validation for upload file

Sometimes you need, uploaded validate or not over spring-content-jpa dependency.
But I am failed to validate uploaded file.

my validation code like this,

if (!(product.getMimeType().contains(".jpeg")||product.getMimeType().contains(".jpg")||
				product.getMimeType().contains(".png"))||product.getMimeType().contains(".gif")) {
			errors.rejectValue("mimeType", null, "Please upload a valid image.");
			
		}

How to solve this issue?

cllient-side caching using http headers

I was trying to make use of client side caching with Spring Content. One of the ways to do it with Spring Data Rest is by using http headers such as ETag or Last-Modified, which can be included in the response if corresponding java annotations are used ( such as @Versioin for Etag and @LastModifiedDate for Last-Modified).
Unfortunately, Spring content doesn't pick up on these annotations and does not return needed headers, more than that, using @Version annotation causes the exception being thrown while trying to upload file to entity:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.orm.ObjectOptimisticLockingFailureException: Object of class [com.package.ClassName] with identifier [59284]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.package.ClassName#59284]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
	at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:888)

However, the file does upload.

So the question is, is it possible to include this kind of headers to the response without writing custom controller ?

Change ContentStore save directory

How do i change the default directory where the ContentStore stores its contents? I've tried adding spring.content.fs.filesystemRoot=mypath to the application.properties file but nothing happens. And if it is possible i would like to remove the random naming the scheme so i can use the same directories after restarting the server

spring-content S3 doesn't allow path-based bucket access

Paul,
Based on our email conversation, I'm adding an issue here in regards to the fact that the current spring-content codebase doesn't allow path-based bucket access. It only allows access like "./" and not "//". The cause that you mentioned is the fact that the implementation of "EnableS3Stores" and "EnableS3ContentRepositories" performs an @import of the "ContextResourceLoaderConfiguration".

After implementing the "S3ClientOptions.setPathStyleAccess(true)" in the @configuration file, as mentioned in the email, it got farther, but ran into an issue around the AmazonS3Client @bean. I got this error:

Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'contentEntityRestController' defined in URL [jar:file:/C:/Users/rzcp0f/.m2/repository/com/github/paulcwarren/spring-content-rest/0.0.4-SNAPSHOT/spring-content-rest-0.0.4-SNAPSHOT.jar!/internal/org/springframework/content/rest/controllers/ContentEntityRestController.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'contentStoreService': Unsatisfied dependency expressed through method 'setFactories' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'sopDocumentContentStore': Unsatisfied dependency expressed through field 'client'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.amazonaws.services.s3.AmazonS3' available: expected single matching bean but found 2: getAmazonS3Client,amazonS3

Based on that error, I had to add @primary to the AmazonS3Client @bean in my @configuration file. Once I did that, it is now communicating with our internal S3 repository and storing data. (sorry about the poor formatting - I'm not familiar enough with the markup to get it working)

My Example @configuration file now:

@configuration
@componentscan
@EnableJpaRepositories
@EnableS3ContentRepositories
public class ApplicationConfig extends AbstractS3StoreConfiguration {

@Value("${spring.content.s3.url:#{environment.AWS_URL}}")
private String url;

@Value("${spring.content.s3.accessKey:#{environment.AWS_ACCESS_KEY}}")
private String accessKey;

@Value("${spring.content.s3.secretKey:#{environment.AWS_SECRET_KEY}}")
private String secretKey;

@Value("${spring.content.s3.bucket:#{environment.AWS_BUCKET}}")
private String bucket;

@Override
public SimpleStorageResourceLoader simpleStorageResourceLoader() {
    return new SimpleStorageResourceLoader(getAmazonS3Client(getBasicAWSCredentials()));
}

@Bean
public BasicAWSCredentials getBasicAWSCredentials() {
    return new BasicAWSCredentials(accessKey, secretKey);
}

@Bean
S3ClientOptions getS3ClientOptions() {
    S3ClientOptions opts = new S3ClientOptions();
    opts.setPathStyleAccess(true);
    return opts;
}

@Bean @Primary
public AmazonS3Client getAmazonS3Client(AWSCredentials awsCredentials) {
    AmazonS3Client amazonS3Client = new AmazonS3Client(awsCredentials);
    amazonS3Client.setEndpoint(url);
    amazonS3Client.setS3ClientOptions(getS3ClientOptions());
    return amazonS3Client;
}

}

Filesystem root property

Does the spring.content.fs.filesystemRoot property actually work? I set it to /media/content (a directory which exists on the filesystem) but it's not used at all. Am I doing something wrong?

close resources

in this class no resource is ever closed (connection, resultset, statement). Which java version is this project targeted to (8?)?

Upload to S3 missing mime type

Files uploaded to S3 does not have the appropriate Content-Type metadata. It is all default to application/octet-stream.

Even if I have provided @MimeType String mimeType = "image/jpeg", the information is not passed to S3.

I think it can be easily fixed. We should be able to customize the content type of the file

Make content repository/store root configurable on a per content repository basis.

From @bilak >>>>

From current implementation it looks like when I want new FS content store (CS) then I need to create new entity/spring repository/content repository for it. There could be an option where all contents will be stored in one entity/content store and somehow partitioned. Let's create annotation @FileSystemPartition (or maybe some name which fits better) for entity field which will split contents in partitions on FS (e.g. /filesystemroot/partition1 /filesystemroot/partition2). For this there also need to be some @ContentId generator which will guarantee the correct "sequence" id generation.

interface PartitionContentIdGenerator {
   Object generateIdForPartition(Object partition);
}

Maybe parameter and return type should be of Long type.

MySQLBlobResource always returns text 'content' as value of content column

       @Override
	protected String getSelectBlobSQL(Object id) {
		return "SELECT id, 'content' as content FROM BLOBS WHERE id='" + id + "'";
	}

this always returns string: 'content' as result for content column

Should be:

       @Override
	protected String getSelectBlobSQL(Object id) {
		return "SELECT id, content as content FROM BLOBS WHERE id='" + id + "'";
	}

Composit Spring Content Services with CMIS

Hi Paul,

First of all, GREAT project!

I work in an enterprise with multiple ECM's and one of them is scheduled to be EOL'ed, and therefore a candidate to be replaced by a Spring Content alternative. I'm pretty sure that this can be done with the current feature set, and the release of the upcoming "Versioning" support.

I still see mentions of CMIS in the docs, can you say anything about how far away the support/implementation of this standard is?
The reason that I'm asking, is that we would like to expose all our ECM's as one, and be able to search across them via Elastic Search(ES).

So basically, I thinking two layer setup:
1 FRONT END:
A ECM Facade Service based on Spring Content, Writes metadata to ES, Stores Content to multiple ECM backends. (Spring Content CMIS)
2 BACK END:
Pure ECM backend A (soap services, CMIS) Fronted by Spring Content "proxy service"(Spring Content CMIS)
Pure ECM backend B (stored procedures) Fronted by Spring Content "proxy service" (Spring Content CMIS)
Pure Spring Content Service (ES, File system or RDB) (Spring Content CMIS)

So the facade would be the single entry point for all queries, and the "only" one to call the backend ECM services.

Do you see anything alarming in this setup? We should have have a common interface between the Facade and the backends (both proxies and Spring Content services) - here I'm thinking "Spring Content CMIS" could play a role?
Also the repository abstraction in CMIS could play well in terms of controlling which backend actually stores the content data.

That said I'm pretty new to CMIS so any thoughts you have are welcome.

Spring Content S3 - Rest

Hey!

First off, I want to say I love this project, I found it just recently and it's exactly what I need.

I'm trying to stand up a spring boot project using the s3 starter and the rest starter, but I'm having some trouble.

I've been able to POST/GET to the endpoints but as far as I can tell it's not doing anything with s3. I've configured the AmazonS3 client and defined the bucket, region, etc.

This is what I have right now for store and repo:

@RepositoryRestResource
public interface DocumentRepository extends JpaRepository<Document, Long> {}

@StoreRestResource
public interface DocumentContentStore extends ContentStore<Document, Long> {}

The document and config are exact replicas of yours from the examples. (i.e. with all the annotaions on the entity and the @configuration & @EnableS3Stores on the configuration class.

Can you point me towards the most up-to-date example on how to start getting CRUD operations with an s3 bucket? Or if you know something that's wrong with my set up?

Thanks in advance!

Why Stores and renditions return InputStream and not resource

Hello Warren!

First of all,

Nice Work!

I fork your spring-content and do some customization in.
We did port to spring boot 2.0.x (tests are green, all seems work)
We renamed "spring-content-" to "strg-spring-" so maybe in future it will not clash with spring it self.
I start to meet some strange behaviors. One what I meet yesterday was:
ContentEntityRestController.getContent(... ) ["ranged"] request handler do this call:

Resource r = ((Store)info.getImpementation()).getResource(cid);

And it finish in exception cause ContentStores are designed to return InputStream.
As I found, debugging my tryes, underline spring handling is more Resource oriented. So here is my question: "Is there any reason why Stores return InputStream and not Resource?" In all Implementations You get resource from storage and then you just return InputStream of resource anyway.
If there is no particular reason I will try change Store / renditions interface to work directly with Resources, so I will have more flexibility. I will add caching aspect to the renditions, cause we are strongly oriented in media conversion, so we need save as much resource moving up and down as possible.

Next one is: <video...> html5 tag from chrome call correctly call before described handler, instead of mozilla call other one, where underlying spring after try to make ranged response and fail cause InputStreamResource is not good for ranged response. I did small fix ( I return Resource it self ) and mozilla stream well too.

I'd like to be useful to you as much as possible in my work time :)
I'm at start of development, so I'm just looking around inside code for now, and I study how I'll move in the future.

Regards

Ladislav

content-rest mappings hide data rest endpoints for "PATCH" and "HEAD" methods

ContentHandlerMapping#lookupHandlerMethod returns lookup method for mapping, unfortunately because ContentHandlerMapping#isHalOrJsonRequest ignores "PATCH" and "HEAD" methods, rest endpoints created by Spring Data Rest get hidden and therefor it's impossible to perform "PATCH" update on "content entity" and "PUT" update with content-type header application/json erases file. It would be great if the support for these methods was added as well!

basePackageClasses for packages in external libraries

We use an internal library which enables a FilesystemStore using the following config class:

  @Configuration
  @EnableFilesystemStores(basePackageClasses = {ContentStores.class})
  public static class FileStoreConfig {

  }

This configuration is included from within the spring boot context in our applications. The creation of the ContentStores defined in the ContentStores package are working fine when starting from within the IDE, but fail when deployed on the server.

Does the basePackageClasses support using classes in external libraries?

Question regarding file save path

Hello,

We have started using this library in our new project and we were wondering is it possible to save every file in different directory? We have defined "spring.content.fs.filesystemRoot" in our application.properties as "/opt/files", and we would like for each file to have its own parent folder inside filesystemRoot. For example, if UUID is "78e604ec-391c-47c4-8014-db3430796dae", the path to file would be "/opt/files/78e604ec/78e604ec-391c-47c4-8014-db3430796dae" (the parent folder should be root + first part of UUID).

Thank you in advance for your answer!

Override JpaContentTemplate

I'm trying to use a sql server backend which doesn't work with the sql in the JpaContentTemplate. What is the best way to override the bean that is created in JpaStoresRegistrar? Would be great if spring boot autoconfig looked for an existing bean. Setting my bean as @primary and giving it the same name is also not working.

Ability to Support "Attachments"

I want to use Spring-Content however I have a requirement of content having related "attachments" such as images, pdfs, etc. Have you thought of extending and adding support for related content? If not I can take a shot at adding basic support. Can you give any pointers on where to start?

Thanks.

Mongo Solr - No Qualified Conversion Service Bean Error

When setting up spring-content to use both mongodb and solr I am getting a runtime error on spring startup. I am following these instructions

Field contentConversionService in org.springframework.content.solr.FullTextSolrIndexingConfig required a single bean, but 4 were found:
       - mongoStoreConverter: defined by method 'mongoStoreConverter' in internal.org.springframework.content.mongo.config.MongoStoreConfiguration
       - mvcConversionService: defined by method 'mvcConversionService' in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]
       - defaultConversionService: defined by method 'defaultConversionService' in class path resource [org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.class]
       - solrConversionService: defined by method 'solrConversionService' in class path resource [internal/org/springframework/content/solr/boot/autoconfigure/SolrAutoConfiguration.class]

I believe this is stemming from the Configuration Class FullTextSolrIndexingConfig.

My dependencies in my pom file look like this thus far:

<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-rest</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-mongodb</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>com.github.paulcwarren</groupId>
			<artifactId>spring-content-mongo-boot-starter</artifactId>
			<version>${spring.content.version}</version>
		</dependency>
		<dependency>
			<groupId>com.github.paulcwarren</groupId>
			<artifactId>spring-content-renditions-boot-starter</artifactId>
			<version>${spring.content.version}</version>
		</dependency>
		<dependency>
			<groupId>com.github.paulcwarren</groupId>
			<artifactId>spring-content-rest-boot-starter</artifactId>
			<version>${spring.content.version}</version>
		</dependency>
		<dependency>
			<groupId>com.github.paulcwarren</groupId>
			<artifactId>spring-content-solr-boot-starter</artifactId>
			<version>${spring.content.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.solr</groupId>
			<artifactId>solr-solrj</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.codehaus.woodstox</groupId>
					<artifactId>wstx-asl</artifactId>
				</exclusion>
				<exclusion>
					<artifactId>log4j</artifactId>
					<groupId>log4j</groupId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

I also have my SolrClient Configured:
@Bean public SolrClient solrClient(){ return new HttpSolrClient.Builder(environment.getProperty("solr.host")).build(); }

My Mongo GridFsTemplate is also configured. I am running my mongo, solr, and my spring boot app in a docker environment using docker-compose for now.

Fields in superclass are not set

Seems like BeanUtils.getFieldWithAnnotation and BeanUtils.setFieldWithAnnotation do not search for annotated fields in superclasses, thus limiting the use of inheritance.

PlacementService not using custom ContentID converter

Hi Paul,

Congratulations on a very nice project you created.
I've decided to give it a go for a system I'm building but I cannot seem to get the PlacementService to use my custom @ContentId converter.

I have an entity

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class Document {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    private String hash;
    private String originalName;

    @ContentId
    private UUID contentId;
    @ContentLength
    private Long contentLen;
    @MimeType
    private String mimeType = "application/pdf";
}

And a configuration class that defines a S3StoreConfigurer to add my custom converter

@Configuration
public class S3StoreConfiguration {

    private String s3ObjectKeyPrefix;

    @Autowired
    public S3StoreConfiguration(@Value("${app.s3ObjectKeyPrefix}") final String s3ObjectKeyPrefix) {
        this.s3ObjectKeyPrefix = s3ObjectKeyPrefix;
    }

    @Bean
    public S3StoreConfigurer configurer() {
        return new S3StoreConfigurer() {

            @Override
            public void configureS3StoreConverters(ConverterRegistry registry) {
                // Do not replace anonymous class with lambda otherwise spring won't be able to determine source type <S> and target type <T> for your Converter
                registry.addConverter(new Converter<UUID, String>() {

                    @Override
                    public String convert(final UUID source) {
                        return String.format("/%s/%s", s3ObjectKeyPrefix, source.toString());
                    }
                });
            }

            @Override
            public void configureS3ObjectIdResolvers(S3ObjectIdResolvers resolvers) {
                // deprecated
            }
        };
    }
}

As you can see what I want is to inject a default object key prefix in all the objects in my bucket.
However, when I run this I still get the UUID.toString() as a key.
I've debugged my code and it seems that the PlacementService is always using a generic converter while I do see it holds a reference to my custom converter in the list of converters.

I did implement a resolver (which seem deprecated in favour of converters) and that worked when storing the objects but not when retrieving them.

Do you have any idea of what am I doing wrong?

file don't upload using spring content

try to upload file using spring but can't.
here is stack trace,

java.lang.IllegalStateException: Error processing condition on internal.org.springframework.content.jpa.boot.autoconfigure.JpaContentAutoConfiguration.databaseInitializer
at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:64) ~[spring-boot-autoconfigure-2.0.2.RELEASE.jar:2.0.2.RELEASE]
at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:108) ~[spring-context-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod(ConfigurationClassBeanDefinitionReader.java:180) ~[spring-context-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:141) ~[spring-context-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:117) ~[spring-context-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:328) ~[spring-context-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:233) ~[spring-context-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:273) ~[spring-context-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:93) ~[spring-context-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:694) ~[spring-context-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:532) ~[spring-context-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) [spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:395) [spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:327) [spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1255) [spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1243) [spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
at com.onlineshopping.OnlineShoppingApplication.main(OnlineShoppingApplication.java:10) [main/:na]
Caused by: java.lang.IllegalStateException: @ConditionalOnMissingBean did not specify a bean using type, name or annotation and the attempt to deduce the bean's type failed
at org.springframework.boot.autoconfigure.condition.OnBeanCondition$BeanSearchSpec.validate(OnBeanCondition.java:389) ~[spring-boot-autoconfigure-2.0.2.RELEASE.jar:2.0.2.RELEASE]
at org.springframework.boot.autoconfigure.condition.OnBeanCondition$BeanSearchSpec.(OnBeanCondition.java:379) ~[spring-boot-autoconfigure-2.0.2.RELEASE.jar:2.0.2.RELEASE]
at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchOutcome(OnBeanCondition.java:114) ~[spring-boot-autoconfigure-2.0.2.RELEASE.jar:2.0.2.RELEASE]
at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47) ~[spring-boot-autoconfigure-2.0.2.RELEASE.jar:2.0.2.RELEASE]
... 17 common frames omitted
Caused by: org.springframework.boot.autoconfigure.condition.OnBeanCondition$BeanTypeDeductionException: Failed to deduce bean type for internal.org.springframework.content.jpa.boot.autoconfigure.JpaContentAutoConfiguration.databaseInitializer
at org.springframework.boot.autoconfigure.condition.OnBeanCondition$BeanSearchSpec.addDeducedBeanTypeForBeanMethod(OnBeanCondition.java:442) ~[spring-boot-autoconfigure-2.0.2.RELEASE.jar:2.0.2.RELEASE]
at org.springframework.boot.autoconfigure.condition.OnBeanCondition$BeanSearchSpec.addDeducedBeanType(OnBeanCondition.java:426) ~[spring-boot-autoconfigure-2.0.2.RELEASE.jar:2.0.2.RELEASE]
at org.springframework.boot.autoconfigure.condition.OnBeanCondition$BeanSearchSpec.(OnBeanCondition.java:373) ~[spring-boot-autoconfigure-2.0.2.RELEASE.jar:2.0.2.RELEASE]
... 19 common frames omitted
Caused by: java.lang.NoClassDefFoundError: org/springframework/boot/autoconfigure/AbstractDatabaseInitializer
at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_171]
at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[na:1.8.0_171]
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.8.0_171]
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) ~[na:1.8.0_171]
at java.net.URLClassLoader.access$100(URLClassLoader.java:73) ~[na:1.8.0_171]
at java.net.URLClassLoader$1.run(URLClassLoader.java:368) ~[na:1.8.0_171]
at java.net.URLClassLoader$1.run(URLClassLoader.java:362) ~[na:1.8.0_171]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_171]
at java.net.URLClassLoader.findClass(URLClassLoader.java:361) ~[na:1.8.0_171]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_171]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) ~[na:1.8.0_171]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_171]
at org.springframework.util.ClassUtils.forName(ClassUtils.java:274) ~[spring-core-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.boot.autoconfigure.condition.OnBeanCondition$BeanSearchSpec.addDeducedBeanTypeForBeanMethod(OnBeanCondition.java:436) ~[spring-boot-autoconfigure-2.0.2.RELEASE.jar:2.0.2.RELEASE]
... 21 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.autoconfigure.AbstractDatabaseInitializer
at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_171]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_171]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) ~[na:1.8.0_171]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_171]
... 35 common frames omitted

Spring Content S3 - CannedAccessControlList support

Are there any plans to support set the level of access to files?
For example:

PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, fileName, file)
                .withCannedAcl(CannedAccessControlList.PublicRead);

ResourceHttpRequestHandler warnings

After adding spring-content-fs-boot-starter and spring-content-rest-boot-starter (version 0.5.0) to my a spring boot 2.0.4 project I receive some warnings on application start.

The warnings are:

o.s.w.s.r.ResourceHttpRequestHandler - Locations list is empty. No resources will be served unless a custom ResourceResolver is configured as an alternative to PathResourceResolver.

f.a.AutowiredAnnotationBeanPostProcessor - Inconsistent constructor declaration on bean with name 'contentPropertyCollectionRestController': single autowire-marked constructor flagged as optional - this constructor is effectively required since there is no default constructor to fall back to: public internal.org.springframework.content.rest.controllers.ContentPropertyCollectionRestController(org.springframework.context.ApplicationContext,org.springframework.content.commons.storeservice.ContentStoreService,internal.org.springframework.content.rest.mappings.StoreByteRangeHttpRequestHandler)

f.a.AutowiredAnnotationBeanPostProcessor - Inconsistent constructor declaration on bean with name 'contentPropertyRestController': single autowire-marked constructor flagged as optional - this constructor is effectively required since there is no default constructor to fall back to: public internal.org.springframework.content.rest.controllers.ContentPropertyRestController(org.springframework.context.ApplicationContext,org.springframework.content.commons.storeservice.ContentStoreService,internal.org.springframework.content.rest.mappings.StoreByteRangeHttpRequestHandler)

I've tried upgrading to spring boot 2.1.1 and this causes the application not to start:

***************************
APPLICATION FAILED TO START
***************************

Description:

The bean 'contentRestExceptionHandler', defined in class path resource [org/springframework/content/rest/config/RestConfiguration.class], could not be registered. A bean with that name has already been defined in URL [jar:file:/home/user/.m2/repository/com/github/paulcwarren/spring-content-rest/0.5.0/spring-content-rest-0.5.0.jar!/internal/org/springframework/content/rest/controllers/ContentRestExceptionHandler.class] and overriding is disabled.

Action:

Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true

Setting spring.main.allow-bean-definition-overriding=true in application.properties resolves the issue with application start on 2.1.1 however the following warning still remains:

o.s.w.s.r.ResourceHttpRequestHandler - Locations list is empty. No resources will be served unless a custom ResourceResolver is configured as an alternative to PathResourceResolver.

ContentStore.setContent doesn't set content id

Issue is related to spring-content-fs, i didn't check other modules.

tl;dr

If an entity has a constructor which accepts a single String argument ContentStore's setContent method

  • doesn't set the entity's field annotated with @ContentId
  • does create a file which name is equal to the entity's toString output (e.g. package.ClassName@1d9bd4d6)

Example Project

Details

The entity's contentId field is only set when a resource is found for that entity. To find the resource the content store checks if the conversion service can convert the entity to a string.
If the entity has a constructor which accepts a single string the conversion service can actually convert this entity to a string (entity's toString method). This string is then used as the resource location and a non-null resource is returned to setContent, which leads to the not-set contentId field and the creation of a file with name equal to the entity's toString output.

Support for spring-cloud-aws 2

We're upgrading our applications to spring boot 2 and spring 5 which causes our apps containing spring-content to fail with java.lang.ClassNotFoundException: org.springframework.cloud.aws.core.io.s3.SimpleStorageResourceLoader

I've created a sample project demonstrating the issue: https://github.com/pulse00/spring-content-boot-2.

I've seen a spring-boot-2 branch (https://github.com/paulcwarren/spring-content/tree/wip/springboot2), which has no recent activity.

Are we missing something? If not, can we help migrating to spring boot 2 / spring-cloud 2?

NoSuchMethodError with JPA and Vaadin

When adding Spring Data and Spring Content JPA to a Vaadin application, created from :
https://vaadin.com/start/latest/project-base-spring

The application returns the below errors. The easiest way to receive the error is to navigate to a Route that doesn't exist. I tried different version of Vaadin and Spring Content, H2, and MySql, with the same errors.

Using Vaadin 12.0.3
Spring content 0.4.0.
Spring Boot: 2.1.0.RELEASE

Attached is a sample project.
sc_error.zip

Errors:
2018-12-21 15:27:20.191 ERROR 22343 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Servlet execution threw an exception] with root cause

java.lang.NoSuchMethodError: org.apache.commons.io.IOUtils.toString(Ljava/io/InputStream;Ljava/nio/charset/Charset;)Ljava/lang/String;
at com.vaadin.flow.router.RouteNotFoundError.readHtmlFile(RouteNotFoundError.java:75) ~[flow-server-1.2.3.jar:1.2.3]

suggestion: remove empty dir on contentRepository.unsetContent

Hi Paul,

I have noticed that when I call unsetContent the dirs are not removed.
In general I think that the sequence...

// file system status = A
myContentRepository.setContent(myEntity, inputStream);
myContentRepository.unsetContent(myEntity);
// file system status = B

... should keep the file system unchanged (A = B).

Regards,
Antonio

How to download a file from a content store

When i try to download a file from the server onto the disk i get an error saying server problem and in the server log i get "java.lang.UnsupportedOperationException: null
"

content-s3-spring-boot-starte and S3ObjectId

Hi Paul.

Thank you so much for your hard work.

From API reference

Ultimately, the S3 store uses instances of S3ObjectId to identify and place content. It is therefore also possible to create S3 stores using this type as the @ContentID type.

My dependencies

  ...
  springBootVersion = '2.0.6.RELEASE'
  contentVersion = '0.3.0'
  ...
@Entity
@Data
public class FileEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(name = "description", length = 50)
    private String description;

    @ContentId
    private S3ObjectId contentId;
//    private String contentId;

//    @Bucket
//    private String bucket;

    @ContentLength
    private long contentLength;

    @Column(name = "mime_type", nullable = false, length = 100)
    private String contentMimeType;

}

But... when I change type object (String -> S3ObjectId)... I get an exception:
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.util.UUID] to type [com.amazonaws.services.s3.model.S3ObjectId]

Suggestion: DefaultFilesystemStoreImpl.setContent() should throw Exceptions in case of failure

For example, if the target directory for the content is not writeable, a IOError is thrown in the body of the setContent() method, but it is recovered with the code

logger.error(String.format("Unexpected error setting content for resource %s",property.toString()), e);

I think that it would be better to throw an exception (something like CannotSetContent...) or, at least, the method should return a boolean with the status of the operation (eg: true for success and false for fail).

Thank you and best regards,
Antonio

Unable to make text searchable REST call with app built with JHipster

http://localhost:8080/documents/searchContent/findKeyword?keyword=TEXT_SEARCH_WORD

org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.lang.Long] for value 'searchContent'; nested exception is java.lang.NumberFormatException: For input string: "searchContent"
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:43)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:203)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:187)
at internal.org.springframework.content.rest.controllers.AbstractContentPropertyController.findOne(AbstractContentPropertyController.java:114)
at internal.org.springframework.content.rest.controllers.ContentPropertyCollectionRestController.get(ContentPropertyCollectionRestController.java:146)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
at com.codahale.metrics.servlet.AbstractInstrumentedFilter.doFilter(AbstractInstrumentedFilter.java:111)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:110)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at com.cah.ecm.daas.security.jwt.JWTFilter.doFilter(JWTFilter.java:36)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:96)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:347)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:263)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:64)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.SessionRestoringHandler.handleRequest(SessionRestoringHandler.java:119)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:332)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NumberFormatException: For input string: "searchContent"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Long.parseLong(Unknown Source)
at java.lang.Long.valueOf(Unknown Source)
at org.springframework.util.NumberUtils.parseNumber(NumberUtils.java:211)
at org.springframework.core.convert.support.StringToNumberConverterFactory$StringToNumber.convert(StringToNumberConverterFactory.java:62)
at org.springframework.core.convert.support.StringToNumberConverterFactory$StringToNumber.convert(StringToNumberConverterFactory.java:49)
at org.springframework.core.convert.support.GenericConversionService$ConverterFactoryAdapter.convert(GenericConversionService.java:436)
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:37)
... 117 common frames omitted

Create better strategy for storing content on filesystem

Current FS implementation stores contents in one directory. This will lead to performance issue/bottleneck because (from my experiences) storing more than 10000 contents to one directory doesn't have good impact on FS/OS.

This could help:
Instead of working with UUID, just persist entity with Long/Integer etc... what will autoincrement the sequence. Then hash (hex) this number. For instance if the path of store could be something like /XX/XX/XX/ZZZ.extension then potentially there could be 16760438784 contents in one store (if I counted it correctly). XX is in range 0-255 (256), ZZZ is range 1-999 (999 if we don't start with number 0).

If I can help somehow with pull request let me know, but I'm just reading codebase so it can take some time to understand it.

in a Spring Boot application Store Converters are invoked by Spring Web MVC when attempting to convert controller arguments

Store Converters used to convert IDs are actually being used by the webmvc controller argument resolver which is definitely unexpected/unintended system behavior.

This unintended invocation causes conversion of the repository and id arguments which can cause failure of the content controllers.

Given that in a Spring Boot application ALL converters get added to the webmvc conversion service, we should either be using a stronger typing; e.g. Converter<String,ContentId> or we shouldn't be using the Converter interface at all (which ironically we weren't doing originally).

spring-content-s3-boot-starter drags spring-data-jpa dependency

In my use case 0.4.0 worked fine, but 0.5.0 now drags spring-data-jpa into classapth, but I am not using spring-data-jpa (I am not usiing spring-data directly at all) which results in NoClassDefFound when autoconfiguration kicks in (it can't find javax/persistence/EntityManagerFactory).

The chain is:
spring-content-s3-boot-starter -> spring-content-s3 -> spring-content-commons -> spring-versions-commons -> spring-data-jpa

At the end, non-optional spring-data-jpa dependency is present. Is it intentional?

DefaultS3StoreImpl doesn't allow dynamic buckets

Hi Paul,

first of all thanks for this very nice piece of work.

In our use case we have not only one bucket for our s3 storage, but several, namely one for each customer. So we would like to set the customer id as property of the @Entity and use this customer id as bucket name. As far as I can see, this is not possible with the DefaultS3StoreImpl, as thie private method absolutify() uses the bucket of the DefaultS3StoreImpl within the storage path.

What do you think would be the best way, to use a property of the entity as bucket name? Should absolutify() be protected, so it could be overwritten accordingly?

What is your opinion on that?

Kind regards,

Tobias

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.