halbuilder / halbuilder-core Goto Github PK
View Code? Open in Web Editor NEWHalBuilder Core
HalBuilder Core
Hi,
This issue applies to v5.0.1, 5.0.2-SNAPSHOT (and the current "develop" branch).
The insertion order of embedded resources is not preserved.
The example code
ResourceRepresentation< ? > resource = ResourceRepresentation.create( new HashMap<>() );
resource = resource
.withLink( "foo", "/foo/1" )
.withRepresentation( "foo", ResourceRepresentation.create( new HashMap<>() )
.withLink( "self", "/foo/1" ) )
.withLink( "foo", "/foo/2" )
.withRepresentation( "foo", ResourceRepresentation.create( new HashMap<>() )
.withLink( "self", "/foo/2" ) )
.withLink( "foo", "/foo/3" )
.withRepresentation( "foo", ResourceRepresentation.create( new HashMap<>() )
.withLink( "self", "/foo/3" ) );
System.out.println( JsonRepresentationWriter.create( new ObjectMapper() ).print( resource ).utf8() );
results in the following output:
{
"_links" : {
"foo" : [ {
"href" : "/foo/1"
}, {
"href" : "/foo/2"
}, {
"href" : "/foo/3"
} ]
},
"_embedded" : {
"foo" : [ {
"_links" : {
"self" : {
"href" : "/foo/3"
}
}
}, {
"_links" : {
"self" : {
"href" : "/foo/1"
}
}
}, {
"_links" : {
"self" : {
"href" : "/foo/2"
}
}
} ]
}
}
While the links seem to follow the insertion order the embedded resources don't. I don't know if this is actually a bug. The HAL spec is not specific here. But since links and embedded resources are JSON arrays they probably should match the insertion order.
The issue might be fixed by changing ResourceRepresentation.java:103 from
TreeMultimap.withSet().empty();
to
TreeMultimap.withSeq().empty();
and the constructor in ResourceRepresentation.java:141 accordingly.
Regards,
Markus
Given the following:
RepresentationFactory rf = new StandardRepresentationFactory()
.withFlag(RepresentationFactory.PRETTY_PRINT);
return rf.newRepresentation("/orders")
.withNamespace("acme", "http://docs.acme.com/relations/{rel}")
.withLink("acme:widgets", "/widgets")
.toString(RepresentationFactory.HAL_JSON);
I expected to get a single object for the acme:widgets
link, thus:
{
"_links" : {
"curies" : [ {
"href" : "http://docs.acme.com/relations/{rel}",
"name" : "acme",
"templated" : true
} ],
"self" : {
"href" : "/orders"
},
"acme:widgets" : {
"href" : "/widgets"
}
}
}
(Cf. the example in Section 8.2, "Link Relations", of the HAL Internet Draft, which is identical apart from more compact formatting and swapping the order of the self
and curies
properties.)
Instead, I get acme:widgets
as a single-element array:
{
"_links" : {
"curies" : [ {
"href" : "http://docs.acme.com/relations/{rel}",
"name" : "acme",
"templated" : true
} ],
"self" : {
"href" : "/orders"
},
"acme:widgets" : [ {
"href" : "/widgets"
} ]
}
}
How do I create a singular link?
Hi,
This issue applies to v5.0.1-SNAPSHOT (and/or the current "develop" branch).
As soon as you add a second representation with .withRepresentation()
or use .withRel(Rels.collection())
the representations are moved out of the _embedded
elements to the outer element.
A single .withRepresentation("item", ...)
is added to _embedded
as expected:
{
"_embedded": {
"item": {
...
}
}
}
But if I use .withRel(Rels.collection("item")
or add a second .withRepresentation("item", ...)
the _embedded
elements is empty and the representations are moved to the outer object:
{
"_embedded": {},
"item": [
{
...
},
...
]
}
The problem seems to be JsonRepresentationWriter.java:145 which uses
objectNode.set(rel.rel(), embedArrayNode);
instead of
embedsNode.set(rel.rel(), embedArrayNode);
A question aside from the issue:
When will v5.0.1 be available on Maven Central? Apart the from the mentioned issue v5.0.1-SNAPSHOT seems to work perfectly for me. The README.md
hints that I should use com.theoryinpractise:halbuilder5:5.0.1-SNAPSHOT
from Maven Central. But unfortunately I'm not allowed to use any SNAPSHOT dependencies from Maven Central. Our artifact repository won't even download them.
Regards,
Markus
Hi,
This feature request applies to v5.0.1, 5.0.2-SNAPSHOT (and the current "develop" branch).
Since halbuilder5
uses a different representation object, we cannot use halbuilder-jaxrs
. Instead I used a MessageBodyWriter
pretty similar to the one from halbuilder-jaxrs
. Since JSON reading and writing is included in halbuilder5
it might be a good idea to include the JAX-RS related stuff (MessageBodyReader
and MessageBodyWriter
) as well.
@Provider
@Produces( { "application/hal+json", "application/hal+xml" } )
public class JaxRsHalBuilderSupport< T > implements MessageBodyWriter< T >
{
@Context
private Providers providers;
@Override
public boolean isWriteable( Class< ? > type, Type genericType, Annotation[] annotations, MediaType mediaType )
{
return ResourceRepresentation.class.isAssignableFrom( type ) && HalBuilderMediaTypes.isSupported( mediaType );
}
@Override
public long getSize( T t, Class< ? > type, Type genericType, Annotation[] annotations, MediaType mediaType )
{
return -1;
}
@Override
public void writeTo( T t, Class< ? > type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap< String, Object > httpHeaders, OutputStream entityStream ) throws IOException, WebApplicationException
{
ResourceRepresentation< ? > representation = (ResourceRepresentation< ? >) t;
if( mediaType.isCompatible( HalBuilderMediaTypes.HAL_JSON_TYPE ) ) {
JsonRepresentationWriter writer = Optional
.ofNullable(providers.getContextResolver( ObjectMapper.class, HalBuilderMediaTypes.HAL_JSON_TYPE ) )
.map( resolver -> resolver.getContext( ObjectMapper.class ) )
.map( JsonRepresentationWriter::create )
.orElseGet( JsonRepresentationWriter::create );
writer.write( representation, new OutputStreamWriter( entityStream, HalBuilderMediaTypes.DEFAULT_ENCODING ) );
}
else if( mediaType.isCompatible( HalBuilderMediaTypes.HAL_XML_TYPE ) ) {
//TODO Provide a writer for HAL+XML.
throw new RuntimeException( "No writer available for media type '" + mediaType + "'" );
}
else {
throw new RuntimeException( "No writer available for media type '" + mediaType + "'" );
}
}
}
We don't currently need HAL+XML. Thus we throw an exception here. Also I don't have a MessageBodyReader
implementation for ResourceRepresentation
yet.
Regards,
Markus
Hi,
seems that example in README is wrong. Where it says ๐
String xml = halResource.toString(ResourceFactory.HAL_XML);
String json = halResource.toString(ResourceFactory.HAL_JSON);
it would be:
String xml = halResource.toString(RepresentationFactory.HAL_XML);
String json = halResource.toString(RepresentationFactory.HAL_JSON);
http://tools.ietf.org/html/draft-kelly-json-hal-05#section-8.2
The draft appears to indicate "curies" rather than "curie", as well as using an array representation for the curies, even if there is only one.
The output I get from Halbuilder is a singlar curie without an array representation for a single curie.
When I include HalBuilder 5 in a Gradle project, I get warnings like these on compilation:
warning: unknown enum constant Flavour.Vavr
reason: class file for org.derive4j.Flavour not found
warning: unknown enum constant ArgOption.checkedNotNull
reason: class file for org.derive4j.ArgOption not found
warning: unknown enum constant Make.constructors
reason: class file for org.derive4j.Make not found
warning: unknown enum constant Make.getters
warning: unknown enum constant Make.casesMatching
My workaround was to include derive4j-annotation
as a compile-only dependency (loosely equivalent to Maven provided
scope):
compile 'com.theoryinpractise:halbuilder5:5.1.2'
compileOnly 'org.derive4j:derive4j-annotation:0.12.3' // avoid HalBuilder-related compile warnings
(The down side of this is I'm hypothetically passing the problem along to anybody that depends on my code, but this particular project is an application rather than a library so that's not likely. In a library, I'd probably have to just make it an explicit compile
dependency.)
I don't know what happens in straight Maven, but it seems to me provided
might be the wrong scope for the Derive4J libraries, since it doesn't seem likely that it's going to be literally provided by a JDK or container.
Hi,
This issue applies to v5.0.1, 5.0.2-SNAPSHOT (and the current "develop" branch).
Representations with empty value produce an NPE:
ResourceRepresentation< ? > resource = ResourceRepresentation.empty()
.withLink( "foo", "/foo" )
.withRepresentation( "foo", ResourceRepresentation.create( new HashMap<>() )
.withLink( "self", "/foo" ) );
results in
Exception in thread "main" java.lang.NullPointerException
at com.theoryinpractise.halbuilder5.json.JsonRepresentationWriter.renderJsonProperties(JsonRepresentationWriter.java:159)
at com.theoryinpractise.halbuilder5.json.JsonRepresentationWriter.renderJson(JsonRepresentationWriter.java:104)
at com.theoryinpractise.halbuilder5.json.JsonRepresentationWriter.write(JsonRepresentationWriter.java:66)
at com.theoryinpractise.halbuilder5.json.JsonRepresentationWriter.print(JsonRepresentationWriter.java:60)
since the corresponding JsonNode
is NULL
in renderJsonProperties()
. A NULL
check before JsonRepresentationWriter.java:159 seems to fix the problem. It's not a big issue though since you can easily work around by using
ResourceRepresentation.create( new HashMap<>() )
instead of
ResourceRepresentation.empty()
but since empty()
exists it should not throw an NPE.
Regards,
Markus
Google Guava version 15 replaces a lot of toImmutableList
method names to the more simpler toList
style - this causes...... issues.
HalBuilder should be updated to work with Guava 15.
java.lang.NoSuchMethodError: com.google.common.collect.FluentIterable.toSortedImmutableList(Ljava/util/Comparator;)Lcom/google/common/collect/ImmutableList;
at com.theoryinpractise.halbuilder.impl.representations.BaseRepresentation.getNaturalLinks(BaseRepresentation.java:140)
at com.theoryinpractise.halbuilder.impl.representations.BaseRepresentation.getCanonicalLinks(BaseRepresentation.java:78)
at com.theoryinpractise.halbuilder.impl.representations.BaseRepresentation.validateNamespaces(BaseRepresentation.java:231)
at com.theoryinpractise.halbuilder.impl.representations.BaseRepresentation.toString(BaseRepresentation.java:288)
at com.theoryinpractise.halbuilder.impl.representations.BaseRepresentation.toString(BaseRepresentation.java:279)
at com.theoryinpractise.halbuilder.impl.representations.BaseRepresentation.toString(BaseRepresentation.java:274)
at smx3.resource.CustomerResource.represent(CustomerResource.java:169)
Currently, when using halbuilder-json, I can only specify a global setting for whether to serialize single element arrays as arrays or items for _links/_embedded.
For my use case, I would like to be able to have single elements arrays treated as just the item for links, but for a specific embedded resource link relation, always serialize it as an array, even with only element.
As far as API, I could see:
withRepresentation
with a parameter to specify always being an array: repFactory.newRepresentation().withRepresentation('orders', myOrder, true)
repFactory.newRepresentation().setArrayRelationship('orders')
repFactory.withArrayRelationship('orders')
Thoughts?
The renaming of *Resource to *Representation solidifies the fact that HalBuilder is a representation library and not a resource library, as part of this change it makes sense that an HREF is dictated by the REST library/framework in use, and NOT HalBuilder.
Therefore we should remove any usage of the com.theoryinpractise.halbuilder.DefaultRepresentationFactory#baseHref field, including the constructor, and any relative URI resolution.
This also solves a tricky problem of trying to resolve relative URIs that are NOT URLs.
When adding a link or creating a new representation I'm unable to add a title attribute to a link element.
I haven't found any documentation specifying how to do it either. I believe this would be a good thing to have because the hal-browser displays this information to provide additional detail about a link.
Hi,
In order to add selft link I'm using HALBuilder with a Jersey Filter to complete my response.
So after invoked newRepresentation(String path) method I add entity to my representation thanks to withBean method.
The class representing my entity has a field annotated @JsonIgnore. I would like to ignore this kind of field
Here is the code
Representation representation = this.newRepresentation(uriInfo.getPath());
representation.withBean(entity);
Regards,
Since halbuilder5 is now shaping to be a totally separate project, the current develop
branch should be pushed to a halbuilder5
repository and the current develop branch reset to the contents of the support/4.x branch.
Hi,
This feature request applies to v5.0.1, 5.0.2-SNAPSHOT (and the current "develop" branch).
The documentation mentions a static method
JsonRepresentationReader.create(ObjectMapper objectMapper)
However this method does not exist. Currently there is a constructor that creates a new ObjectMapper
:
public JsonRepresentationReader() {
this.mapper = new ObjectMapper();
}
A static method that can be used to inject the ObjectMapper
provided by the JAX-RS ContextResolver
would be quite helpful. Also making the constructor private and instead adding the static factory methods
JsonRepresentationReader.create(ObjectMapper objectMapper)
and
JsonRepresentationReader.create(Module... modules)
would make JsonRepresenationReader
very much consistent with JsonRepresentationWriter
.
Regards,
Markus
I have written a T getBean(Representation representation, Class value); Added to the Representation Interface for tag 4.0.3, locally. The reason for tag 4.0.3 because the getProperties method has the fix to recursively check if the value is a JSONArray or JSONObject. Therefore the properties map has the correct values.
The reason for the method is because when you read in hal+json for building up a bean entity based on the properties map. You will have to iterate through the property map and for the matching/marshalling to a bean entity, the casting is done manually for each bean field. Therefore having a getBean method reduces the tedious job of this. The getBean method is based upon the jackson objectMapper.readValue.
Was wondering if this would be a helpful feature?
If an interface has a Map or List/Collection field type, and that type matches the actual property value type in the representation, it should be returned directly.
It should depend on 2.2.1 instead of 2.2.1-SNAPSHOT.
In BaseRepresentation class, the following code snippet:
public String toString(String contentType, final Set<URI> flags) {
StringWriter sw = new StringWriter();
toString(contentType, flags, sw);
return sw.toString();
}
Will violate JSON standard when
-Dfile.encoding=UTF-8
is not givenThis is due to StringWriter
will use the platform encoding when writing out its contents, converting its buffer in the process.
The combination of these conditions will result in a JSON response that is not encoded in UTF-8.
Snippet to test:
import java.io.*;
public class Test {
public static void main(String... args) {
StringWriter w = new StringWriter();
w.append("\u65E5\u672C\u8A9E");
System.out.println(w.toString());
}
}
Example:
โ LC_ALL=en_US java Test
???
โ LC_ALL=en_US java -Dfile.encoding=utf-8 Test
ๆฅๆฌ่ช
โ LC_ALL=en_US.utf-8 java Test
ๆฅๆฌ่ช
โ LC_ALL=en_US.utf-8 java -Dfile.encoding=iso-8859-1 Test
???
example is currently:
.withLink("/todo-list/search;{searchterm}", "td:search")
.withLink("/todo-list/description", "td:description")
should be:
.withLink("td:search", "/todo-list/search;{searchterm}")
.withLink("td:description", "/todo-list/description")
f.setCodec(new ObjectMapper());
Update the JSON renderer to use ObjectMapper to serialize out arrays, and on the Reader to read in arrays.
Also look at how to handle this on XML?
Should these also auto magically deserialize?
Hi,
This issue applies to v5.1.1, 5.1.2-SNAPSHOT (and the current "develop" branch).
There seems to be no way to add an empty array as an _embedded
object, e.g. with
ResourceRepresentation< ? > resource = ResourceRepresentation.empty( "/" )
.withLink( "items", "/items" )
.withRepresentation( "items", ResourceRepresentation.empty( "/items" )
.withRel( Rels.collection( "item" ) ) );
System.out.println( JsonRepresentationWriter.create( new ObjectMapper() ).print( resource ).utf8() );
I get the following output:
{
"_links" : {
"self" : {
"href" : "/"
},
"items" : {
"href" : "/items"
}
},
"_embedded" : {
"items" : {
"_links" : {
"self" : {
"href" : "/items"
}
}
}
}
}
Since I used .withRel( Rels.collection( "item" ) )
I expected the output to include an empty array:
{
"_links" : {
"self" : {
"href" : "/"
},
"items" : {
"href" : "/items"
}
},
"_embedded" : {
"items" : {
"_links" : {
"self" : {
"href" : "/items"
}
},
"item" : [ ]
}
}
}
The code
ResourceRepresentation< ? > resource = ResourceRepresentation.empty( "/" )
.withLink( "items", "/items/1" )
.withRepresentation( "items", ResourceRepresentation.empty( "/items/1" )
.withRel( Rels.collection( "item" ) )
.withRepresentation( "item", ResourceRepresentation.empty() ) );
results in "item": [ { } ]
which is not correct.
The code
ResourceRepresentation< ? > resource = ResourceRepresentation.empty( "/" )
.withLink( "items", "/items/1" )
.withRepresentation( "items", ResourceRepresentation.empty( "/items/1" )
.withRel( Rels.collection( "item" ) )
.withRepresentation( "item", ResourceRepresentation.create( Collections.EMPTY_LIST ) ) );
results in an Exception:
Exception in thread "main" java.lang.IllegalStateException: Unable to serialise a non Object Node
at com.theoryinpractise.halbuilder5.json.JsonRepresentationWriter.renderJsonProperties(JsonRepresentationWriter.java:151)
...
The code
ResourceRepresentation< ? > resource = ResourceRepresentation.empty( "/" )
.withLink( "items", "/items" )
.withRepresentation( "items",
ResourceRepresentation.create( "/items", ImmutableMap.of( "item", Collections.EMPTY_LIST ) ) );
actually provides the expected result although it seems to be more of a work around to set the value
of the ResourceRepresentation
to an object { "list": [ ] }
. The bad thing of this work around is that we will need a check for an empty list beforehand and if it's empty, we create this representation, else we create the "normal" representation. It might be a good idea to make the initial example with .withRel( Rels.collection( "item" ) )
lead to the same result.
Regards,
Markus
And the same for representation.getLinkByRel.
Also, may be it will be nice to have ability to get resource links in form of map with "rel" as key, and list of matching links as value (like representation.getResourceMap).
Only the rel of the last link is actually added to the previously existing rels. The reason seems to be that rels.put()
actually returns a new tree on which the rel is added.
Thus the following code
final TreeMap<String, Rel> updatedRels =
links
.map(Links::getRel)
.foldLeft(
rels,
(accum, rel) -> !accum.containsKey(rel) ? rels.put(rel, Rels.natural(rel)) : rels);
should rather be:
final TreeMap<String, Rel> updatedRels =
links
.map(Links::getRel)
.foldLeft(
rels,
(accum, rel) -> !accum.containsKey(rel) ? accum.put(rel, Rels.natural(rel)) : accum);
The issue can be verified by:
ResourceRepresentation<HashMap<Object, Object>> withLinks =
ResourceRepresentation.create("/self", HashMap.empty())
.withLinks(List.of(Links.create("link1", "/link1"), Links.create("link2", "/link2")));
JsonRepresentationWriter jsonRepresentationWriter = JsonRepresentationWriter.create();
ByteString representation = jsonRepresentationWriter.print(withLinks);
which will throw an exception.
On Android 4.4 the library does not work, it crashes with the following trace error:
02-12 15:05:59.842 14367-15000/ro.assist.bookingbugandroid I/dalvikvm: Could not find method java.beans.Introspector.getBeanInfo, referenced from method com.theoryinpractise.halbuilder.impl.representations.MutableRepresentation.withBean
02-12 15:05:59.842 14367-15000/ro.assist.bookingbugandroid W/dalvikvm: VFY: unable to resolve static method 46929: Ljava/beans/Introspector;.getBeanInfo (Ljava/lang/Class;)Ljava/beans/BeanInfo;
02-12 15:05:59.842 14367-15000/ro.assist.bookingbugandroid D/dalvikvm: VFY: replacing opcode 0x71 at 0x0004
02-12 15:05:59.852 14367-15000/ro.assist.bookingbugandroid W/dalvikvm: VFY: unable to resolve exception class 5409 (Ljava/beans/IntrospectionException;)
02-12 15:05:59.852 14367-15000/ro.assist.bookingbugandroid W/dalvikvm: VFY: unable to find exception handler at addr 0x33
02-12 15:05:59.852 14367-15000/ro.assist.bookingbugandroid W/dalvikvm: VFY: rejected Lcom/theoryinpractise/halbuilder/impl/representations/MutableRepresentation;.withBean (Ljava/lang/Object;)Lcom/theoryinpractise/halbuilder/api/Representation;
02-12 15:05:59.852 14367-15000/ro.assist.bookingbugandroid W/dalvikvm: VFY: rejecting opcode 0x0d at 0x0033
02-12 15:05:59.852 14367-15000/ro.assist.bookingbugandroid W/dalvikvm: VFY: rejected Lcom/theoryinpractise/halbuilder/impl/representations/MutableRepresentation;.withBean (Ljava/lang/Object;)Lcom/theoryinpractise/halbuilder/api/Representation;
02-12 15:05:59.852 14367-15000/ro.assist.bookingbugandroid W/dalvikvm: Verifier rejected class Lcom/theoryinpractise/halbuilder/impl/representations/MutableRepresentation;
02-12 15:05:59.862 14367-15000/ro.assist.bookingbugandroid W/dalvikvm: threadid=11: thread exiting with uncaught exception (group=0x41c96d58)
02-12 15:05:59.952 14367-15000/ro.assist.bookingbugandroid E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: ro.assist.bookingbugandroid, PID: 14367
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:300)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
Caused by: java.lang.VerifyError: com/theoryinpractise/halbuilder/impl/representations/MutableRepresentation
at helpers.hal_addon.CustomJsonRepresentationReader.readResource(CustomJsonRepresentationReader.java:51)
at helpers.hal_addon.CustomJsonRepresentationReader.read(CustomJsonRepresentationReader.java:44)
at com.theoryinpractise.halbuilder.DefaultRepresentationFactory.readRepresentation(DefaultRepresentationFactory.java:96)
at bookingbugAPI.services.HttpService.callApi(HttpService.java:198)
at bookingbugAPI.services.HttpService.callApi(HttpService.java:135)
at bookingbugAPI.services.HttpService.api_POST(HttpService.java:103)
at bookingbugAPI.models.BBRoot.auth(BBRoot.java:69)
at ro.assist.bookingbugandroid.data.tasks.AdminLogin.doInBackground(AdminLogin.java:59)
at ro.assist.bookingbugandroid.data.tasks.AdminLogin.doInBackground(AdminLogin.java:14)
at android.os.AsyncTask$2.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)ย
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)ย
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)ย
at java.lang.Thread.run(Thread.java:841)ย
Could you please push the latest version to maven?
I ran into a bug at DefaultRepresentationFactory.lookupRenderer(String contentType). The mediatype does not get parsed correctly, after properly removing the "application/" prefix it tries to match the subtypes "hal+json;charset=utf-8" with "hal+json", which of course aren't equal.
The function seems to have gotten a major overhaul and should work, but there are only old versions on maven. I'll try to get the ";charset=utf-8" postfix removed on my side, but I'd really prefer to just use the latest Halbuilder.
When the content type {application/hal+json;q=1000}
is passed in the request header it does not "match" any ContentType in the DefaultRepresentationFactory.lookupRenderer() method.
The result is:
! java.lang.IllegalArgumentException: Unsupported contentType: {application/hal+json, q=1000}
! at com.theoryinpractise.halbuilder.DefaultRepresentationFactory.lookupRenderer(DefaultRepresentationFactory.java:116) ~[halbuilder-core-4.0.3.jar:na]
! at com.theoryinpractise.halbuilder.impl.representations.BaseRepresentation.toString(BaseRepresentation.java:295) ~[halbuilder-core-4.0.3.jar:na]
! at com.theoryinpractise.halbuilder.impl.representations.BaseRepresentation.toString(BaseRepresentation.java:289) ~[halbuilder-core-4.0.3.jar:na]
! at com.theoryinpractise.halbuilder.jaxrs.JaxRsHalBuilderSupport.writeTo(JaxRsHalBuilderSupport.java:36) ~[halbuilder-jaxrs-1.1.1.jar:na]
It seems like the com.theoryinpractise.halbuilder.impl.ContentType
constructor should handle relative quality factors if they are part of the content type string.
In the follow code the print(...)
method throws NPE when try to get the type of the tree.
ResourceRepresentation<Void> empty = ResourceRepresentation.empty();
JsonRepresentationWriter writer = JsonRepresentationWriter.create();
ByteString jsonBS = writer.print(empty);
System.out.println(jsonBS.utf8());
The empty resource should be printed into {}
string. This would be empty JSON document.
On another hand because empty JSON is not valid HAL document I guess factory call ResourceRepresentation.empty()
should not be allowed.
The same problem exists even of I provide href for self link. So any call to empty(...) produces invalid ResourceRepresentation instance.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.