Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ContentStore bean #203

Open
xLegna opened this issue May 3, 2020 · 12 comments
Open

ContentStore bean #203

xLegna opened this issue May 3, 2020 · 12 comments

Comments

@xLegna
Copy link

xLegna commented May 3, 2020

I have a question to use ContentStore.

package gettingstarted;

import org.springframework.content.commons.repository.ContentStore;

public interface FileContentStore extends ContentStore<File, String> {
}

To use my contentStore like this:
@Autowired private FileContentStore contentsRepo;

This is my interface, should I add @repository to the interface?
Who should create the bean FileContentStore?

@Vmarci94
Copy link

Vmarci94 commented May 4, 2020

it interests me too.
image
This code is working, but not too nice.

@paulcwarren
Copy link
Owner

paulcwarren commented May 5, 2020

Hi @Vmarci94,

To use my contentStore like this:

@Autowired private FileContentStore contentsRepo;

Yes that is how you can autowire the content store into another part of your code in order to make use of it.

This is my interface, should I add @repository to the interface?

No, that is a Spring Data construct. Spring Content does not require this.

Who should create the bean FileContentStore?

Spring Content will create it for you. When your application starts Spring Content will see the FileContentStore and it will see spring-content-fs on your classpath and inject a proxy.

This code is working, but not too nice.

Not too nice because the IDE has underlined it?

@Vmarci94
Copy link

Vmarci94 commented May 8, 2020

Thank You the quick answer.

Sorry the "not too nice" expression. Rather a little confusing to my reviewers. They are very trusting in Intellij IDEA ...

Although You said, the @reposirtoy annotation is a Spring Data construct, and Spring Content does not required this, I added the @component annotation and solved this little thing.

I would have another question. Although I don't think you'll be happy for him.
So I want to set file names, because the directory is a remote drive and several others process use this files. I think this api not entirely for that.

I found DefaultFilesystemStoreImpl class and EnableFilesystemContentRepositories.storeFactoryBeanClass method, i thought write a customFilesystemStoreImpl, but i see the EnableFilesystemContentRepositories annotation is Deprecated. I would be interested in another solution. Do you think I can solve this?

@paulcwarren
Copy link
Owner

Although You said, the @reposirtoy annotation is a Spring Data construct, and Spring Content does not required this, I added the @component annotation and solved this little thing.

Ah I see what you are saying. This is an IDE thing then. Intellij, in this case, needs to know it is a bean otherwise it will flag it as an error. Although, in our case, spring content stores are bean and will be wired correctly. Just intellij doesn't know that. I will work on this. It would be fine to add a bean annotation on Store so developers don't have annotate their store interfaces directly.

I would have another question. Although I don't think you'll be happy for him.
So I want to set file names, because the directory is a remote drive and several others process use this files. I think this api not entirely for that.

Each Store Module (except JPA) has a placement service that is responsible for locating the content in the backing store. This placement service can be configured through a standard Spring converter. It can be done in a couple of ways depending on requirements. Sounds like you know what you want to call the file so I would suggest something like this.

Assume you have a Document entity like this:

@Entity
@Data
public class Document {

    @Id
    @GeneratedValue(strategy=AUTO)
    private Long id;

    @ContentId
    private UUID contentId;

    @ContentLength
    private Long contentLength;

    @MimeType
    private String mimeType;

    private String contentPath;
}

Then you can add a configurer like this:

	@Configuration
	public static class StoreConfig {
		@Bean
		public FilesystemStoreConfigurer configurer() {
			return new FilesystemStoreConfigurer() {

				@Override
				public void configureFilesystemStoreConverters(ConverterRegistry registry) {
					registry.addConverter(new Converter<Document, String>() {

						@Override
						public String convert(Document document) {
							return document.getContentPath();
						}
					});
				}
			};
		}
	}

Now, when you set content for an instance of Document, the placement service will call the converter to establish where to store that contnet.

So, if you created a Document and set its contentPath to /some/path/my-file. Then your content will be stored in your backing store (remote share) at /some/path/my-file.

Would this solve your problem?

@paulcwarren
Copy link
Owner

I updated the docs for the filesystem module to (hopefully) explain this better: https://paulcwarren.github.io/spring-content/refs/snapshot/1.0.x/fs-index.html#_accessing_content

@paulcwarren
Copy link
Owner

I looked into the problem marker that you highlighted. I also see this BTW. And it is annoying. But I suspect that there are smarts in the spring plugins that make this work for Spring Data repositories.

We would need to add a similar plugin for Spring Content.

@andye2004
Copy link
Contributor

andye2004 commented Jun 6, 2021

@paulcwarren, I only just saw this but there are no plugin changes required my friend. Simply add the internal.org.springframework.content package to the @ComponentScan and it should 'just work' E.g.

@SpringBootApplication
@ComponentScan(basePackages = "internal.org.springframework.content")
public class Application {
}

The issue with just using the plain @SpringBootApplication is that it will only include beans defined within the 'default' package (the package in which the Application class) is defined and it's sub-packages, as well as the Spring beans. Anything outside of these things has to be added to the @ComponentScan as a package using basePackages or as a class using basePackageClasses to be picked up.

FYI @xLegna, @Vmarci94

@paulcwarren
Copy link
Owner

Thanks for the info.

Yeah, I think what is weird for me about this is that you don't need this @ComponentScan application for the correct functioning of the application. intellij's error is in reality a false negative.

Eclipse for example, doesn't exhibit this behavior so (I'm assuming) the eclipse spring plugins generally solve this (on behalf of the developer) and intellij solves it for known spring projects but not others like this one.

We can definitely add this @ComponentScan to our spring boot starters as that will have no effect for eclipse developers but fix it for intellij developers. But this seems like a bug with the intellij spring problem markers to me.

@andye2004
Copy link
Contributor

Hey Paul, interesting point re eclipse, it must be scanning the entire runtime classpath for bean candidates. I know that the IntelliJ plugin generally doesn't do this and relies on configuration to determine where it resolves beans - I'm guessing this is for performance reasons.

I'm not sure adding @ComponentScan to the SB starters is going to resolve this issue as scanning for the project would still only be done for anything org.spring.... and anything under the default package. Would be good if it did work but my gut says it needs to be added to each project.

@maksym-matlo
Copy link

@paulcwarren I want to store java.sql.Blob with Spring Data. How to configure you dependency in this case and which exactly dependency do I have to use?

@paulcwarren
Copy link
Owner

paulcwarren commented Dec 7, 2022

@maksym-matlo the basic setup is described in the jpa guide here. And you might find the set of jpa integration tests a useful guide also. And lastly it should be pretty simple to adapt any of the getting started guides like the rest one. You would just need to swap out fs storage, for jpa storage.

@mosup16
Copy link

mosup16 commented Mar 1, 2023

@paulcwarren, I only just saw this but there are no plugin changes required my friend. Simply add the internal.org.springframework.content package to the @ComponentScan and it should 'just work' E.g.

@SpringBootApplication
@ComponentScan(basePackages = "internal.org.springframework.content")
public class Application {
}

The issue with just using the plain @SpringBootApplication is that it will only include beans defined within the 'default' package (the package in which the Application class) is defined and it's sub-packages, as well as the Spring beans. Anything outside of these things has to be added to the @ComponentScan as a package using basePackages or as a class using basePackageClasses to be picked up.

I tried this but I got Could not find class [internal.org.springframework.content.jpa.config.JpaStoreFactoryBean]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants