This repository has been archived by the owner on May 26, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
split StorableFile into StorableFile and RetrievableFile
- Loading branch information
amckenzie
authored and
Matt Rich
committed
Jan 23, 2017
1 parent
310fc58
commit 10f960c
Showing
62 changed files
with
2,897 additions
and
1,346 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,54 @@ | ||
# file-service | ||
# File Service [![Build Status](https://travis-ci.org/CJSCommonPlatform/file-service.svg?branch=master)](https://github.com/CJSCommonPlatform/file-service) | ||
|
||
A simple drop in library for storing binary files in Postgres. This library assumes that it is running inside a JEE container with a datasource configured to point at Postgres | ||
|
||
### Maven | ||
|
||
<dependency> | ||
<groupId>uk.gov.justice.services</groupId> | ||
<artifactId>file-service-persistence</artifactId> | ||
<version>1.0.0-SNAPSHOT</version> | ||
</dependency> | ||
|
||
|
||
### To Use | ||
|
||
final JsonObject metadata = ... | ||
final InputStream fileContentStream = ... | ||
|
||
final UUID fileId = fileStorer.store(metadata, fileContentStream); | ||
|
||
final Optional<FileReference> fileReference = fileRetriever.retrieve(fileId); | ||
if(fileReference.isPresent()) { | ||
|
||
// always remember to close the input streams | ||
// as this will also close the database Connection | ||
try(final InputStream inputStream = fileReference.get().getContentStream()) { | ||
// do stuff... | ||
} | ||
} | ||
|
||
### Database and JNDI setup | ||
|
||
There needs to be a Postgres DataSource configured in your container with the JNDI name | ||
|
||
java:/app/fileservice/DS.fileservice | ||
|
||
There is a liquibase script configured to run against a local database. This database should be created as follows: | ||
|
||
database name: fileservice | ||
username: fileservice | ||
password: fileservice | ||
port: 5432 | ||
|
||
To run liquibase there is a bash script in the root folder which will create the tables for you. To run: | ||
|
||
./runLiquibase.sh | ||
|
||
### Issues | ||
|
||
* This implementation is currently Postgres specific: to take advantage of Postgres' *JsonB* data type. | ||
* The integration tests use H2 as an in memory database. | ||
* This implementation currently stores the binary file data in Postgres using it's *bytea* data type. Although bytea will allow storage of up to 1 Gb of data, it isn't recommended to store anything larger than 100 Mb as larger files will unreasonably slow down the database. | ||
* There is an issue with returning the InputStream of the binary content stored in the database. Although closing the SQL Connection before the InputStream is read and closed doesn't cause any issues by itself, using a pooled Connection can cause problems. If the Connection is given to a new request then the InputStream would be null and the previous request would fail. For this reason, we wrap the InputStream in our own InputStream that contains a reference to the database Connection used to read the file. When **close()** is called on the InputStream then the corresponding SQL Connection is also closed. For this reason it is vitally important to remember to close the InputStream in FileReference after use. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<parent> | ||
<artifactId>file-service</artifactId> | ||
<groupId>uk.gov.justice.services</groupId> | ||
<version>1.0.0-SNAPSHOT</version> | ||
</parent> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<artifactId>file-service-api</artifactId> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>javax</groupId> | ||
<artifactId>javaee-api</artifactId> | ||
<scope>provided</scope> | ||
</dependency> | ||
|
||
<!-- Test dependencies --> | ||
<dependency> | ||
<groupId>junit</groupId> | ||
<artifactId>junit</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.hamcrest</groupId> | ||
<artifactId>hamcrest-core</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.mockito</groupId> | ||
<artifactId>mockito-core</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
|
||
</project> |
12 changes: 12 additions & 0 deletions
12
...ice-api/src/main/java/uk/gov/justice/services/fileservice/api/ConfigurationException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package uk.gov.justice.services.fileservice.api; | ||
|
||
public class ConfigurationException extends FileServiceException { | ||
|
||
public ConfigurationException(final String message) { | ||
super(message); | ||
} | ||
|
||
public ConfigurationException(final String message, final Throwable cause) { | ||
super(message, cause); | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
...ice-api/src/main/java/uk/gov/justice/services/fileservice/api/DataIntegrityException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package uk.gov.justice.services.fileservice.api; | ||
|
||
public class DataIntegrityException extends FileServiceException { | ||
|
||
public DataIntegrityException(final String message) { | ||
super(message); | ||
} | ||
|
||
public DataIntegrityException(final String message, final Throwable cause) { | ||
super(message, cause); | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
file-service-api/src/main/java/uk/gov/justice/services/fileservice/api/FileRetriever.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package uk.gov.justice.services.fileservice.api; | ||
|
||
|
||
import uk.gov.justice.services.fileservice.domain.FileReference; | ||
|
||
import java.util.Optional; | ||
import java.util.UUID; | ||
|
||
import javax.json.JsonObject; | ||
|
||
/** | ||
* Entry point for retrieving files from the File Server. Inject This class into you code to use. | ||
*/ | ||
public interface FileRetriever { | ||
|
||
/** | ||
* Retrieves the file corresponding to the specified file id, | ||
* | ||
* @param fileId The id of the file to be retrieved. | ||
* @return an {@link Optional} containing a {@link FileReference} to the requested file, or | ||
* {@code empty()} if none exists | ||
*/ | ||
Optional<FileReference> retrieve(final UUID fileId) throws FileServiceException; | ||
|
||
|
||
/** | ||
* Retrieves the metadata for the file corresponding to the specified file id. | ||
* | ||
* @param fileId The id of the file who's metadata is to be retrieved | ||
* @return an {@link Optional} containing the metadata of the requested file as a {@link JsonObject} | ||
* or {@code empty()} if none exists | ||
*/ | ||
Optional<JsonObject> retrieveMetadata(final UUID fileId) throws FileServiceException; | ||
|
||
} |
12 changes: 12 additions & 0 deletions
12
...rvice-api/src/main/java/uk/gov/justice/services/fileservice/api/FileServiceException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package uk.gov.justice.services.fileservice.api; | ||
|
||
public class FileServiceException extends Exception { | ||
|
||
public FileServiceException(final String message) { | ||
super(message); | ||
} | ||
|
||
public FileServiceException(final String message, final Throwable cause) { | ||
super(message, cause); | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
file-service-api/src/main/java/uk/gov/justice/services/fileservice/api/FileStorer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package uk.gov.justice.services.fileservice.api; | ||
|
||
|
||
import java.io.InputStream; | ||
import java.util.UUID; | ||
|
||
import javax.json.JsonObject; | ||
|
||
/** | ||
* Entry point for Storing files on the File Server. Inject This class into you code to use. | ||
*/ | ||
public interface FileStorer { | ||
|
||
/** | ||
* Stores a new file on the File Server | ||
* | ||
* @param metadata A {@link JsonObject} of the file's metadata | ||
* @param fileContentStream an {@link InputStream} from the file to store | ||
* @return The id of the newly stored file. | ||
*/ | ||
UUID store(final JsonObject metadata, final InputStream fileContentStream) throws FileServiceException; | ||
|
||
/** | ||
* Updates the metadata of the file stored with the specifed id | ||
* | ||
* @param fileId The id of the file who's metadata is to be updated | ||
* @param metadata The metadata to update. | ||
*/ | ||
void updateMetadata(final UUID fileId, final JsonObject metadata) throws FileServiceException; | ||
|
||
/** | ||
* Deletes a file from the file server | ||
* | ||
* @param fileId The id of the file to be deleted. | ||
*/ | ||
void delete(final UUID fileId) throws FileServiceException; | ||
} |
12 changes: 12 additions & 0 deletions
12
file-service-api/src/main/java/uk/gov/justice/services/fileservice/api/StorageException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package uk.gov.justice.services.fileservice.api; | ||
|
||
public class StorageException extends FileServiceException { | ||
|
||
public StorageException(final String message) { | ||
super(message); | ||
} | ||
|
||
public StorageException(final String message, final Throwable cause) { | ||
super(message, cause); | ||
} | ||
} |
55 changes: 55 additions & 0 deletions
55
file-service-api/src/main/java/uk/gov/justice/services/fileservice/domain/FileReference.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package uk.gov.justice.services.fileservice.domain; | ||
|
||
import static java.util.Objects.hash; | ||
|
||
import java.io.InputStream; | ||
import java.util.Objects; | ||
import java.util.UUID; | ||
|
||
import javax.json.JsonObject; | ||
|
||
/** | ||
* Reference to a file stored on the file server. Contains the file's id, the file's metadata as | ||
* a {@link JsonObject} and an {@link InputStream} of the file's content. | ||
*/ | ||
public class FileReference { | ||
|
||
private final UUID fileId; | ||
private final JsonObject metadata; | ||
private final InputStream contentStream; | ||
|
||
public FileReference(final UUID fileId, final JsonObject metadata, final InputStream contentStream) { | ||
this.fileId = fileId; | ||
this.metadata = metadata; | ||
this.contentStream = contentStream; | ||
} | ||
|
||
/** | ||
* @return The id of the file | ||
*/ | ||
public UUID getFileId() { | ||
return fileId; | ||
} | ||
|
||
/** | ||
* @return The metadata of the file as a {@link JsonObject} | ||
*/ | ||
public JsonObject getMetadata() { | ||
return metadata; | ||
} | ||
|
||
/** | ||
* @return An {@link InputStream} of the stored file. | ||
*/ | ||
public InputStream getContentStream() { | ||
return contentStream; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "FileReference{" + | ||
"fileId=" + fileId + | ||
", metadata=" + metadata + | ||
'}'; | ||
} | ||
} |
86 changes: 86 additions & 0 deletions
86
...-service-api/src/main/java/uk/gov/justice/services/fileservice/io/InputStreamWrapper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package uk.gov.justice.services.fileservice.io; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.sql.Connection; | ||
|
||
public class InputStreamWrapper extends InputStream { | ||
|
||
private final InputStream inputStream; | ||
private final Connection connection; | ||
|
||
public InputStreamWrapper( | ||
final InputStream inputStream, | ||
final Connection connection) { | ||
this.inputStream = inputStream; | ||
this.connection = connection; | ||
} | ||
|
||
|
||
@Override | ||
public void close() throws IOException { | ||
|
||
try { | ||
close(inputStream); | ||
} finally { | ||
close(connection); | ||
} | ||
} | ||
|
||
|
||
@Override | ||
public int read() throws IOException { | ||
return inputStream.read(); | ||
} | ||
|
||
@Override | ||
public int read(byte b[]) throws IOException { | ||
return inputStream.read(b); | ||
} | ||
|
||
@Override | ||
public int read(byte b[], int off, int len) throws IOException { | ||
return inputStream.read(b, off, len); | ||
} | ||
|
||
@Override | ||
public long skip(long n) throws IOException { | ||
return inputStream.skip(n); | ||
} | ||
|
||
@Override | ||
public int available() throws IOException { | ||
return inputStream.available(); | ||
} | ||
|
||
@Override | ||
public void mark(int readLimit) { | ||
inputStream.mark(readLimit); | ||
} | ||
|
||
@Override | ||
public void reset() throws IOException { | ||
inputStream.reset(); | ||
} | ||
|
||
@Override | ||
public boolean markSupported() { | ||
return inputStream.markSupported(); | ||
} | ||
|
||
private void close(final AutoCloseable autoCloseable) throws IOException { | ||
try { | ||
autoCloseable.close(); | ||
} catch (Exception e) { | ||
throw new IOException("Failed to close " + autoCloseable.getClass().getSimpleName(), e); | ||
} | ||
} | ||
|
||
public InputStream getInputStream() { | ||
return inputStream; | ||
} | ||
|
||
public Connection getConnection() { | ||
return connection; | ||
} | ||
} |
Oops, something went wrong.