I'm looking to form a QueryDSL Path where there is a Map somewhere in the object hierarchy. If I just have simple object hierarchies, I can do the following, which works:
BooleanBuilder builder = new BooleanBuilder();
Path path = Expressions.path(Outer.class, "root");
path = Expressions.path(Inner.class, path, "inner");
builder.and(Expressions.path(String.class, path, "field").eq("test"));
However, I'm a bit confused when coming to a Map. There doesn't seem to be method parameter to pass in the root path, so I'm just at a loss on what to do. Passing the Path metadata doesn't seem to work, but I really didn't expect it to. And there is also no place to pass in the property name that is the map.
BooleanBuilder builder = new BooleanBuilder();
Path path = Expressions.path(Outer.class, "root");
path = Expressions.mapPath(String.class, String.class, StringPath.class, path.getMetadata()); // What would be the proper way to dive down into the map?
builder.and(Expressions.path(String.class, path, "field").eq("test"));
Clearly I do not understand the proper use of this method, but I am unable to glean what the proper use would be.
Also of note, I'm trying to do this dynamically, so even though I could use Q-generated classes in these examples, that isn't my final goal.
So if I had an object structure of Outer.map[key].field, how could I build a Path to select field?
The closest question I found was QueryDsl web query on the key of a Map field, but that assumes directly accessing a dictionary, not having a dictionary somewhere in the path.
Related
I'm trying to implement a plugin for Ontotext GraphDB. I hope it will compute the distance between two entities via breath first search (see GraphDB as an undirected graph).
I found RDF4J custom function maybe a good way.
public Value evaluate(ValueFactory valueFactory, Value... values) throws ValueExprEvaluationException {
if (values.length!=2 || !values[0].isResource() || !values[1].isResource()){
throw new ValueExprEvaluationException("Usage Wrong");
}
Resource source= (Resource) values[0];
Resource target= (Resource) values[1];
return null;
}
However, I can not get the properties (neighbors) of an entity through Value. And it seems that valueFactory can only create an entity.
Now I sucessfully implement the example on Ontotext GraphDB. But the example only involves the string handling.
Is there any way to access the properties of entity in RDF4J custom function?
Appreciate your reply.
That tutorial is a little out of date unfortunately. See the latest javadoc for the Function interface: it now has a evaluate(TripleSource tripleSource, Value... values) method. The TripleSource can be used to query the current state of the store. It should be possible to use this to get the properties associated with your entity.
I have a yaml file which consist of placeholders to be taken from environment variable. I want to parse it to a custom class. Currently I am using snakeyaml library to parse it and its populating the bean correctly, how can I resolve environment variables using snakeyaml or any other library in Java.
datasource:
url: {url_environment_variable}
foo: bar
username: {user_name_environment_variable}
password: {password_environment_variable}
#Getter
#Setter
public class DataSource {
private String url;
private String foo;
private String username;
private String password;
}
Parsing code below
Constructor c = new Constructor(MyDataSource.class);
Yaml yaml = new Yaml(c);
MyDataSource myData = yaml.loadAs(inputStream, MyDataSource.class);
The problem is I am yet to find a way to resolve placeholders. People were able to solve it using python and is available in question -
How to replace environment variable value in yaml file to be parsed using python script
How can I do the same in Java. I can add a new dependency if required.
PS - It's not a Spring Boot Project so standard Spring placeholder replacements can not be used.
The easiest way would be to do it in two passes. First deserialize into MyDataSource as you’re doing already. Then use reflection to iterate over all fields of the instance, and if the value starts with a curly brace and ends with one, extract the key, and get the value from System.getenv map. See this answer for code.
If you want to do it in one pass, then you need to use the snakeyaml event-driver parser. For every key, you resolve the value as described above, and then based on the key name, set the corresponding field in the MyDataSource class, either using reflection, or simple if-else. For an example of the event-driven parser, see this class; it’s not Java, it’s Kotlin, but it may be the only JVM language example you’ll find.
I am trying to delete resource using id and name, so I have two different methods to delete the resource using id and name. The think I realized later is that this will throw me ambiguous http operation.
example Delete an animal from the database using following operation:
/animal/1 or animal/elephant
I do not believe query parameters is the right answer for this. You are trying to delete a particular resource and I feel path param would be the right answer for it (delete a resource with a sepcific path, query params are mostly used for Getting a resource). However, I am not sure how can I achieve this without getting an exception. Any ideas?
A resource should be identifiable by only one URL, in your case the ID.
Locating the object by other means is a search, aka a query, e.g. by name, even if names are guaranteed to be unique.
So, the following would be good, clear URLs:
/animal/1
/animal?name=elephant
/animal?color=grey
You could also using matrix parameters, e.g. if the tail of an elephant is a resource:
/animal/1/tail
/animal;name=elephant/tail
See URL matrix parameters vs. request parameters.
I am looking to pass a field value to a resolved field using another object type.
Another way to put it if I have `Customer > User > Profile' - how can I pass the CustomerID field value that would be in customer to Profile as an argument or variable in order to resolve correctly?
There's exactly 5 possibilities (as of graphql-java v12) to provide info to a resolver (DataFetcher) at any level:
1) Directly pass them in the query (possibly on multiple levels):
{customer(id: 3) {
user {
profile(id: 3) {
name
}
}
}
}
2) Get values from the source object
The source is the result of the enclosing query.
In your case, the source for the customer query is the root (whatever you provided at the query execution time, e.g.
graphQL.execute(ExecutionInput.newExecutionInput()
.query(query)
.root(root)
.build())
The source for the user query is whatever customer query returned, presumably some Customer instance.
The source for the profile query is whatever the user query returned, presumably a User instance.
You can get a hold of the source via DataFetchingEnvironment#getSource(). So, if User contains the CustomerID you're after, just get it via ((User) env.getSource()).getCustomerId(). If not, consider wrapping the result into an object that would contain all you need in the sub-queries.
3) Pass the values around using the shared context
graphql-java passes around an instance of GraphQLContext available to all resolvers. So, inside the DataFetcher for customer, you can store the CustomerID into it:
Customer customer = getCustomer();
GraphQLContext context = env.getContext();
context.put("CustomerID", customer.getId());
Later on, inside the DataFetcher for profile, you can get it from the context:
String customerId = env.getContext().get("CustomerID");
To initialize a context, pass it when executing the query:
ExecutionInput input = ExecutionInput.newExecutionInput()
.query(operation)
.graphQLContext(new HashMap<>())
.build()
graphQL.execute(query, input);
This way is stateful, thus the hardest to manage, so use it only if all else fails.
4) Directly get the arguments passed to a parent field
ExecutionStepInfo stepInfo = dataFetchingEnvironment.getExecutionStepInfo();
stepInfo.getParent().getArguments(); // get the parent arguments
5) Pass the values around using the local context
Instead of returning the result directly, wrap it into a DataFetcherResult. That way you can also attach any object as a localContext that will be available to all child DataFetchers via DataFetchingEnvironment#getLocalContext()
In Servoy, a development and deployment platform, you have the possibility to use what is called a JSFoundSet which is an object containing record objects defined by its SQL. Such a JSFoundSet is created as follows using the appropriate annotation:
/** #type{JSFoundSet<db:/database/table_name}*/
var fs = null;
from this point on you can use in your code the variable fs to get or set values to the properties of table_name. So if I would create a foundset of table Customer and this table contains the columns id, firstName and lastName, then the Servoy platform provides intellisense that allows me to do this:
fs.id = 1;
fs.firstName = 'John';
fs.lastName = 'Doe';
Since I use a lot of Java too, I wanted to see if I can create something similar of this in Java. So I want to create a class FoundSet of a certain generic type, say of type Customer in our example, after which in my code I can create an object of this class and then access the public fields (set/get) of FoundSet. While typing I wish to see these fields show up through intellisense.
Is there a library or some sort that allows me to define some annotations as the Servoy example to accomplish this?