I don't know how to save a object property of Vertex
buiminhhuy opened this issue · comments
example:
@vertex
public class OAuth2AuthenticationAccessToken extends AbstractDomainEntity {
private static final long serialVersionUID = -3919074495651349876L;
@Index
private String tokenId;
@Property
private OAuth2AccessToken oAuth2AccessToken;
private String authenticationId;
@Index
private String userName;
@Index
private String clientId;
@Property
private OAuth2Authentication authentication;
@Index
private String refreshToken;
//contructor get set
}
Note: OAuth2AccessToken, OAuth2Authentication are two interface of Spring FrameWork. They will instance object when runtime. I don't know how to save them in OrientDB. in them may be have some another Class. May be refer below image.
@buiminhhuy, let me know how you think it should be saved? As a Serialized Object? Which means it has to implement Serializable. How can we save an Object that is not an "entity" or vertex or @Embedded object?
Yes I mean the both two your questions:
- You can save it As a Serialized Object or String (json).
- How can we save an Object that is not an "entity" or vertex or @Embedded object?
Hi @gjrwebber , You have any update for this problem. I think the problem will necessary for your project. When a vertex or Edge have properties type are binary, json object, serialized object,...
@gjrwebber, Help me :D
@buiminhhuy I am working on #21 at the moment. If you want an issue resolved, how about contributing? Fork the repo, branch it, fix it and merge request it :)
Ok @gjrwebber, I am very happy if I am become contributor for your project. I will try to resolve.
@buiminhhuy I have some time now to look at this one. Are you working on it?
No, I am busy for my company project.
ALright, I'll look at it.
I should also note that if you want to ignore the property you can still use transient keyword or @ignore.
ok, Thanks You.
I got a error:
com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class org.springframework.security.oauth2.provider.OAuth2Authentication]: can not instantiate from JSON object (need to add/enable type information?)
at [Source: java.io.StringReader@5df99cba; line: 1, column: 2]
The error occurred because the Object OAuth2Authentication of Spring Framework no constructor suitable.
To resolve the bug, you can supply me how to add a converter to this. Or you can save Object under type binary data.
Before I have implemented for Neo4j by Converter but on your framework, I don't know. You can ref http://stackoverflow.com/questions/28399712/neo4j-tokenstore-spring-oauth2/29910299#29910299 (this link I implement on Neo4j)
Thanks for quick response.
Hi @gjrwebber
I added OAuth2AuthenticationMixin.class to OAuth2AuthenticationAccessToken.
public abstract class OAuth2AuthenticationMixin {
OAuth2AuthenticationMixin(@JsonProperty("oauth2Request") OAuth2Request storedRequest, @JsonProperty("userAuthentication") Authentication userAuthentication) {}
@JsonProperty("oauth2Request") abstract OAuth2Request getOAuth2Request(); // rename property
@JsonProperty("userAuthentication") abstract Authentication getUserAuthentication(); // rename property
}
It seem work ok, but I again get a bug with OAuth2Request, mixin Json as below:
GremlinSchema:236] Could not load property GremlinProperty{name='authentication', accessor=org.springframework.data.gremlin.schema.property.accessor.GremlinJSONFieldPropertyAccessor@76dccb0c, type=class java.lang.String} of <mypackage>.OAuth2AuthenticationAccessToken@abd6d973
java.lang.IllegalStateException: Can not construct instance of org.springframework.security.core.GrantedAuthority, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information
at [Source: java.io.StringReader@677a625a; line: 1, column: 192] (through reference chain: org.springframework.security.oauth2.provider.OAuth2Request["authorities"])
I need implement to deserialize in
@Property
private OAuth2AccessToken oAuth2AccessToken;
Set<String> scope = mapper.readValue(jsonNode.get("scope"), new TypeReference<HashSet<String>>() {});
or for authorities above, because default json parse wrong syntax.
I thinks, I must be add converter to convert as my expectation, before converter as below
public class StringToOAuth2AuthenticationConverter implements Converter<String, OAuth2Authentication> {
@Override
public OAuth2Authentication convert(final String source) {
// some code that takes a String and returns an object of your type
OAuth2Authentication oAuth2Authentication = null;
try {
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(source);
OAuth2Request oAuth2Request = getOAuth2Request(rootNode.get("oauth2Request"), mapper);
JsonNode userAuthentication = rootNode.get("userAuthentication");
JsonNode principal = userAuthentication.get("principal");
UserAccount userAccount = mapper.readValue(principal.get("userAccount"), UserAccount.class);
BBUserDetails userDetails = new BBUserDetails(userAccount);
List<Map<String, String>> authorities = mapper.readValue(userAuthentication.get("authorities"), new TypeReference<List<Map<String, String>>>() {});
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, getAuthorities(authorities));
oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
} catch (IOException e) {
e.printStackTrace();
}
return oAuth2Authentication;
}
private OAuth2Request getOAuth2Request(final JsonNode jsonNode, ObjectMapper mapper) throws JsonParseException, JsonMappingException, IOException{
Map<String, String> requestParameters = mapper.readValue(jsonNode.get("requestParameters"),new TypeReference<Map<String, String>>() {});
String clientId = jsonNode.get("clientId").getTextValue();
List<Map<String, String>> authorities = mapper.readValue(jsonNode.get("authorities"), new TypeReference<List<Map<String, String>>>() {});
Set<String> scope = mapper.readValue(jsonNode.get("scope"), new TypeReference<HashSet<String>>() {});
Set<String> resourceIds = mapper.readValue(jsonNode.get("resourceIds"), new TypeReference<HashSet<String>>() {});
return new OAuth2Request(requestParameters, clientId, getAuthorities(authorities) , true, scope, resourceIds, null, null, null);
}
private Collection<? extends GrantedAuthority> getAuthorities(
List<Map<String, String>> authorities) {
List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>(authorities.size());
for (Map<String, String> authority : authorities) {
grantedAuthorities.add(new SimpleGrantedAuthority(authority.get("authority")));
}
return grantedAuthorities;
}
}
I completed this. as below code:
public abstract class OAuth2AuthenticationMixin {
@JsonCreator
OAuth2AuthenticationMixin(@JsonProperty("oauth2Request") OAuth2Request storedRequest,
@JsonProperty("userAuthentication") Authentication userAuthentication) {}
@JsonDeserialize(using=CustomOAuth2RequestDeserializer.class) abstract OAuth2Request getOAuth2Request(); // rename property
@JsonDeserialize(using=CustomAuthenticationDeserializer.class) abstract Authentication getUserAuthentication(); // rename property
@JsonDeserialize(using=CustomAuthorityDeserializer.class) abstract Collection<? extends GrantedAuthority> getAuthorities(); // rename property
@JsonIgnore abstract Object getPrincipal();
@JsonIgnore abstract Object getCredentials();
@JsonIgnore abstract boolean isClientOnly();
@JsonIgnore abstract String getName();
}