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

How do I add a REST API to read a mp3 file from the predefined folder #521

Closed
BhanuPrakash531 opened this issue Apr 6, 2021 · 5 comments

Comments

@BhanuPrakash531
Copy link

BhanuPrakash531 commented Apr 6, 2021

I have a list of mp3s in my resource folder, I have a JPA implementation with multiple entities. I need to store the filename of the mp3 in the database as part of an entity and I need to read these mp3 as a REST APIs. Please help.
Trying to do as per this example. Spring Content REST but I'm not getting the /dvds/1/image endpoint, server rejects with the error

{
    "timestamp": "2021-04-06T14:01:32.384+00:00",
    "status": 404,
    "error": "Not Found",
    "message": "No message available",
    "path": "/dvds/2/image"
}
@Data
@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Dvd {

   @Id
   @GeneratedValue
   private Long id;

   private String title;

   @OneToOne(cascade = CascadeType.ALL)
   @JoinColumn(name = "image_id")
   private Image image;

   @OneToOne(cascade = CascadeType.ALL)
   @JoinColumn(name = "stream_id")
   private Stream stream;

}
@Data
@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Image {

   // Spring Data managed attribute
   private @Id
   @GeneratedValue
   Long id;

   @OneToOne
   private Dvd dvd;

   // Spring Content managed attributes
   private @ContentId
   UUID contentId;

   private @ContentLength
   Long contentLen;

   @MimeType
   private String mimeType = "text/plain";
}
@Data
@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Stream {

   // Spring Data managed attribute
   private @Id
   @GeneratedValue
   Long id;

   @OneToOne
   private Dvd dvd;

   // Spring Content managed attributes
   private @ContentId
   UUID contentId;

   private @ContentLength
   Long contentLen;

   @MimeType
   private String mimeType = "text/plain";
}
@RepositoryRestResource(path="dvds", collectionResourceRel="dvds")
public interface DvdRepository extends JpaRepository<Dvd, Long> {}


@StoreRestResource
public interface ImageStore extends ContentStore<Image, UUID> {}

@StoreRestResource
public interface StreamStore extends ContentStore<Stream, UUID> {}

<dependency> <groupId>com.github.paulcwarren</groupId> <artifactId>spring-content-fs-boot-starter</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>com.github.paulcwarren</groupId> <artifactId>spring-content-rest-boot-starter</artifactId> <version>1.2.2</version> </dependency>

Please let me know what is the issue.

Thanks in advance.

@paulcwarren
Copy link
Owner

paulcwarren commented Apr 12, 2021

Hi @BhanuPrakash531,

Thanks for raising this issue.

Laying content URIs over entity URIs such as /dvds/{id}/image is a little bit problematic actually especially if the expectation is to POST to /dvds/{id}/image to both create a new image entity (if it doesn't yet exist) and associate content with it in a single atomic operation. POSTing to /dvds/{id}/image to create a new image entity isn't actually supported by Spring Data REST. You have to do something like POST to /images first and then PUT to /dvds/{id}image with a text/uri-list request. So, having Spring Content REST behave differently is probably not a great idea.

It is possible that we could support PUTing to /dvds/{id}/image to associate content (and DELETE to unassociate) but before I do so I need to think through what this means for all data modules. It's fine for JPA, of course, but what would it mean for Mongo, for example, with its Document and more hierarchical data models where content may be nested. Or for Cassandra?

@paulcwarren
Copy link
Owner

Hi @BhanuPrakash531 again.

Further to my previous response. There is a way to get the job done here. Although it means compromising on the content URI. You had previously mentioned using /dvds/<id}/image. But if you add a ImageRepository (and StreamRepository) then you can manage the content directly by:

curl -X POST -H 'Content-Type:application/hal+json' -d '{}' http://localhost:8080/images

to create a new instance of an Image, then:

curl -X PUT -H 'Content-Type:text/plain' -d 'Testing testing testing!' http://localhost:8080/images/2

to set the content, and:

curl -X GET -H 'Accept:text/plain' http://localhost:8080/images/2

to fetch it again.

However, under this alternative you will be responsible for associating the Dvd entity with the Image entity.

HTH

@BhanuPrakash531
Copy link
Author

Thanks @paulcwarren for the detailed explanation. It helped. We can work with this. Also on another project, we have a list of mp3s in resources folder and we don't have any feature to add more mp3s or images. We just need to fetch it from the resources folder where the filename will be set in the pojo on a database and stream it to the UI. What is the best way to do this as per your expert advise? Thanks in advance

@paulcwarren
Copy link
Owner

paulcwarren commented Apr 14, 2021

For your second use case it sounds like you probably just need a Store. Something like:

@StoreRestResource(path = "mystore")
public interface ResourceStore extends Store<String>

Which essentially is just a Spring ResourceLoader. Providing a Java API to fetch content by filename (rather than entity); i.e. myStore.getResource(filename)

The Spring Content REST endpoints for a Store also allow you to fetch content by filename. Something like:

curl -X GET -H 'Accept: video/mp4 http://localhost:8080/mystore/`

Then you can iterate the filenames from the database and for each make requests (or getResource calls) in order to fetch your content.

But honestly, if your resource aren't dynamic at all and the resources are just stored on the filesystem you might just be better off using something like this.

HTH

@paulcwarren
Copy link
Owner

Closing due to inactivity. Feel free to re-open if you would like more help.

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

2 participants