Reputation: 10589
I'm using graphql java tools in my spring application. I have an entity like this:
@Entity
data class Image(
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(nullable = false)
val id: Long = 0
) {
@Lob
@Column(nullable = false)
var image: Blob? = null
}
And in the GraphQL schema I want to have a different type:
type Image {
id: ID!
image: String!
}
Starting this won't work, of course, because of a schema parsing exception.
So I thought it must be possible to put something in between the schema parsing to implement a mapping from Blob
to String
.
Is this somehow possible here?
@Bean
fun schemaParserDictionary(): SchemaParserDictionary {
return SchemaParserDictionary()
}
EDIT
Sorry, it won't give a schema parsing exception. It will simply put the bytes into a string. But I can't use that string then to create the image.
Clarification
Sorry, I guess I was not clear enough with my question. I don't need to know how to transform a blob into a string. There are very easy solutions for that. For example I can use a simple API function to transform byte code into base64:
val base64 = Base64.getEncoder().encodeToString(byteCode)
What I tried to ask was how I can "tell" graphql schema parser to use that "custom" transformation for a specific field. So when my entity object has the field image
with datatype blob
graphql is automatically transforming this to a string
. But the string does not contain the content that I need. So I want to use a custom parsing / mapping / transformation / whatever for that particularly field. Of course, I could also easily get around this by introducing another field which I do not store in the database:
@Entity
data class Image(
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(nullable = false)
val id: Long = 0
) {
@Lob
@Column(nullable = false)
var image: Blob? = null
@Transient
var base64: String = ""
}
but which I make queryable through the graphql api:
type Image {
id: ID!
image: String!
base64: String!
}
type Images {
images: [Image!]!
totalCount: Int!
}
type Query {
getImages: Images!
}
And set it in my controller:
private fun getImages(): Images {
var images: List<Image> = repository.findTop1000()
images.forEach {
it.base64 = Base64.getEncoder().encodeToString(it.image)
queue.offer(it)
}
}
But it would be cleaner if I could tell the graphql schema parser to do that.
Upvotes: 1
Views: 4105
Reputation: 164
Why don't you use a Custom Scalar? It directly answers your starting question:
So I thought it must be possible to put something in between the schema parsing to implement a mapping from Blob to String.
Is this somehow possible here?
You GraphQL schema would be:
scalar ImageBlob
type Image {
id: ID!
image: ImageBlob!
}
Then, in the Custom Scalar implementation, you provide the transformation of a Blob from and to a String.
Upvotes: 1
Reputation: 1143
Kushal's answer provides the snippets to convert a Blob to a String. To use this conversion, it is good practice to use DTO.
To do so, transform your graphql schema to:
type ImageDTO {
id: ID!
image: String!
}
And create a DTO class ImageDTO:
public class ImageDTO {
private Image entity;
//Constructor
public ImageDTO(Image image) {
this.entity=image;
}
//Getters
public Long getId() {
return entity.getId();
}
public String getImage() {
//convert the entity image and return it as String
return Base64.getEncoder().encodeToString(entity.getImage());
}
}
Separating the DTO from the entity grants you a finer control on the data transferred.
Upvotes: 4
Reputation: 45
Let's check it from the beginning. We know that BLOB is an acronym for Binary Large Object used for storing Byte & byte data that exceeds the regular size allowed by the specific datatypes. Converting a BLOB into a string in memory can sometimes cause OutOfMemoryException
if the BLOB data is too large.
But still if you would like to convert BLOB to string here is the code-piece you can try this:
String s = "";
InputStream inStream = b.getBinaryStream();
//b is your BLOB
InputStreamReader inStreamReader = new InputStreamReader(inStream);
BufferedReader reader = new BufferedReader(inStreamReader );
StringBuffer buf = new StringBuffer();
while(s = reader.readLine())
{
buf.append(s);
}
there are several more approach you can take one of them is to
ByteArrayOutputStream baos = new ByteAttayOutputStream();
byte[] buf = new byte[1024];
InputStream in = blob.getBinaryStream();
int n = 0;
while ((n=in.read(buf))>=0)
{
baos.write(buf, 0, n);
}
in.close();
byte[] bytes = baos.toByteArray();
String blobString = new String(bytes);
I would appreciate any further queries from your side.
Upvotes: 2