Writing and Reading Repeated Extended Fields in Protobuf - java

I'm trying to use extensions with Google's Protocol Buffers. I've got one "main" proto file and several other proto files that "extend" the main one.
In my java code, I'm not 100% sure how to add to a repeating message correctly. When I run the java code I've written, the toString() method shows that the extension attributes added, but it doesn't decode properly (probably because I ran a build() call on the added Collar object).
How should I properly add repeating elements to extended items in a proto file?
File1.proto
package protocol_buffer;
option java_outer_classname = "PetClass";
message Pet {
optional string pet_name = 1;
extensions 100 to 199;
}
File2.proto
import "File1.proto";
option java_outer_classname = "CollarClass";
message Collars {
optional string collar_type = 1;
optional string collar_color = 2;
}
extend pet {
repeated Collars collar = 100;
}
MyFile.java
Pet pet = Pet.newBuilder()
.setPetName("Fido")
.addExtension(CollarClass.collar,
Collar.newBuilder()
.setCollarType("round")
.setCollarColor("brown")
.build()
)
.build();
System.out.println(pet.toString());

I figured out my problem. I was correctly adding the extension to "Pet". When parsing a protobuf byte array, you need to add an extension registry so that the function knows what extensions to parse.
ExtensionRegistry registry = ExtensionRegistry.newInstance();
registry.add(CollarClass.collar);
Pet pet = Pet.parseFrom(new FileInputStream(<some file>),registry);

Related

QuickFIX/J Get fields and groups for customized data dictionary

How can I get fields and groups using QuickFIX/J for customized data dictionary?
I receive market data transmitted in customized MarketDataSnapshotFullRefresh (type W) FIX messages. As I understood, I can't use the crack method for this. I'm not quite familiar with Java and QuickFIX/J, but when I use QuickFIX/n and Python, I can define classes for fields and groups like that:
class CustomField(fix.StringField):
tag_number = *SomeTagNumber*
def __init__(self, data=None):
args = (self.tag_number,) if data is None else (self.tag_number, data)
super(CustomField, self).__init__(*args)
def getValue(self, message: object) -> str:
try:
if message.getField(self.tag_number):
return message.getField(self.tag_number)
except fix.FieldNotFound:
return None
else: raise
class CustomGroupField(fix.StringField):
tag_number = *SomeTagNumber*
def __init__(self, data=None):
args = (self.tag_number,) if data is None else (self.tag_number, data)
super(CustomGroupField, self).__init__(*args)
def getValue(self, message: object) -> str:
try:
if message.getField(self.tag_number):
return message.getField(self.tag_number)
except fix.FieldNotFound:
return None
else: raise
class XXXGroup(fix.Group):
def __init__(self):
order = fix.IntArray(4)
order[0] = No_XXX_UMD_Entries.tag_number # This is the NoGroup field
order[1] = XXX_UMD_Entry_ID.tag_number # This is the field in the repeating group
order[2] = CustomGroupField.tag_number
order[3] = 0
# fix.Group.__init__(self, order[0], order[1], order)
args = (order[0], order[1], order)
super(XXXGroup, self).__init__(*args)
def getValue(self, field: object) -> str:
try:
if group.getField(tag_number):
return group.getField(tag_number)
except fix.FieldNotFound:
return None
else: raise
And then I can get value inside the fromApp(self, message, sessionID) method like this:
# Get value of the field
some_custom_field = CustomField().getValue(message)
# Get value in the group
group = XXXGroup()
for idx in range(1, no_entries+1):
message.getGroup(idx,group)
custom_gr_field = group.getValue(CustomGroupField)
How can I achieve the same logic in Java using QuickFIX/J? Or maybe there is a better way to work with a custom data dictionary in Java? Maybe you can refer to some examples?
QuickFIX/J use XML files as Dictionary.
To parse message you should create dictionary and use it. The code looks like:
DataDictionary dataDictionary = new DataDictionary("FIX44.xml");
Message message = new Message();
message.fromString(text, dataDictionary, false);
Standard dictionary stored in quickfixj jars resources. For example, dictionary for FIX 4.4 stores in https://github.com/quickfix-j/quickfixj/blob/master/quickfixj-messages/quickfixj-messages-fix44/src/main/resources/FIX44.xml
For custom dictionary you should create a XML file with all additional fields and groups.
You could copy the standard file, rename it, add group and use like: DataDictionary dataDictionary = new DataDictionary("/var/my_dict/myFIX44.xml");

Get Original Field Name on GraphQL

I'm using https://github.com/leangen/graphql-spqr with spring-boot java application. I can reach to alias name easily but how can I reach to original fieldName?
class Food {
#GraphQLQuery(name = "aliasNameX", description = "A food's name")
private String originalName;
...
}
....
#GraphQLQuery(name = "foods") // READ ALL
#Override
public List<Food> getFoods(#GraphQLEnvironment ResolutionEnvironment env) {
DataFetchingFieldSelectionSet selectionSet = env.dataFetchingEnvironment.getSelectionSet();
List<SelectedField> fields = selectionSet.getFields();
for (SelectedField f: fields)
{
System.out.println(f.getName());
}
return foodRepository.findAll();
}
When I run this code, Output looks like with alias fields: "aliasNameX", ..., but I need original name like "originalName". Is there a way to do it?
Solved, according to:
https://github.com/leangen/graphql-spqr/issues/381
Posting my original answer here as well.
You want the underlying field names, but from a level above. Still possible, but ugly :(
for (SelectedField selectedField : env.dataFetchingEnvironment.getSelectionSet().getImmediateFields()) {
Optional<Operation> operation = Directives.getMappedOperation(selectedField.getFieldDefinition());
String javaName = operation.map(op -> ((Member) op.getTypedElement().getElement()).getName()).orElse(null);
}
Be very careful though. If there's more than one Java element exposed per GraphQL field, getTypedElement().getElement() will explode. So to be sure you'd have to call getTypedElement().getElements() (plural) instead and decide what to do. ClassUtils#getPropertyMembers might also be useful, or the ClassUtils.findXXX family of methods.
You'd basically have to do this:
List<AnnotatedElement> elements = getTypedElement().getElements();
//Look for a field and use its name
Optional<String> field = Utils.extractInstances(elements, Field.class).findFirst().map(Field::getName);
//Look for a getter and find its associated field name
Optional<String> getter = Utils.extractInstances(elements, Method.class).findFirst().map(ClassUtils::getFieldNameFromGetter);
This API might have to change in future, as SDL-based tools are proliferating, so complex directives like the ones SPQR is using are causing problems...

How to duplicate fields names with proto3 oneof feature?

Proto3 supports the oneof features, where you can have a message with many fields and where at most one field will be set at the same time.
Since one field will be set at a time, it would be reasonable to have duplicate field names in the proto schema. The problem is the proto generater sees this as a redefinition.
I'd like to do this because in my situation, this makes json serialization with JsonFormat simple.
For example, I may like to have
message MyResponse {
int32 a = 1;
string b = 2;
oneof Properties {
PropertiesType1 properties = 3;
PropertiesType2 properties = 4;
PropertiesType3 properties = 5;
PropertiesType4 properties = 6;
}
}
Is there a way around this, or will have to make the effort of redefining the proto? A possible work around may be for example to use map<string, Properties> properties = 9;
Ignore the JSON but for now; in most languages/frameworks, you are going to access those properties by their name, whether that is getting the value, or checking which one is set. If the names conflict: you can't do that.
Also: anyof allows the same type to be used for multiple of the members in a discriminated union, in which case what you want to do gets ever more confusing.
Finally, going back to JSON: the parser sees "properties": - what does it expect next? And once it has parsed the value, what field is considered "set" in the discriminated union?
So no, for many reasons: this isn't allowed.
I have solved similar use case for JSON serialization using this way.
message MyResponse {
int32 a = 1;
string b = 2;
oneof Properties {
PropertiesType1 properties1 = 3 [json_name = "properties"];
PropertiesType2 properties2 = 4 [json_name = "properties"];
PropertiesType3 properties3 = 5 [json_name = "properties"];
PropertiesType4 properties4 = 6 [json_name = "properties"];
}
}
This would work if you use protoc compilers but it wont work for advanced tools like buf lint/build. Hope this helps.
But as #marc gravell said this is not recommended way.

Simple Code to Copy Same Name Properties?

I have an old question sustained in my mind for a long time. When I was writing code in Spring, there are lots dirty and useless code for DTO, domain objects. For language level, I am hopeless in Java and see some light in Kotlin. Here is my question:
Style 1 It is common for us to write following code (Java, C++, C#, ...)
// annot: AdminPresentation
val override = FieldMetadataOverride()
override.broadleafEnumeration = annot.broadleafEnumeration
override.hideEnumerationIfEmpty = annot.hideEnumerationIfEmpty
override.fieldComponentRenderer = annot.fieldComponentRenderer
Sytle 2 Previous code can be simplified by using T.apply() in Kotlin
override.apply {
broadleafEnumeration = annot.broadleafEnumeration
hideEnumerationIfEmpty = annot.hideEnumerationIfEmpty
fieldComponentRenderer = annot.fieldComponentRenderer
}
Sytle 3 Can such code be even simplified to something like this?
override.copySameNamePropertiesFrom (annot) { // provide property list here
broadleafEnumeration
hideEnumerationIfEmpty
fieldComponentRenderer
}
First Priority Requirments
Provide property name list only one time
The property name is provided as normal code, so as to we can get IDE auto complete feature.
Second Priority Requirements
It's prefer to avoid run-time cost for Style 3. (For example, 'reflection' may be a possible implementation, but it do introduce cost.)
It's prefer to generated code like style1/style2 directly.
Not care
The final syntax of Style 3.
I am a novice for Kotlin language. Is it possible to use Kotlin to define somthing like 'Style 3' ?
It should be pretty simple to write a 5 line helper to do this which even supports copying every matching property or just a selection of properties.
Although it's probably not useful if you're writing Kotlin code and heavily utilising data classes and val (immutable properties). Check it out:
fun <T : Any, R : Any> T.copyPropsFrom(fromObject: R, vararg props: KProperty<*>) {
// only consider mutable properties
val mutableProps = this::class.memberProperties.filterIsInstance<KMutableProperty<*>>()
// if source list is provided use that otherwise use all available properties
val sourceProps = if (props.isEmpty()) fromObject::class.memberProperties else props.toList()
// copy all matching
mutableProps.forEach { targetProp ->
sourceProps.find {
// make sure properties have same name and compatible types
it.name == targetProp.name && targetProp.returnType.isSupertypeOf(it.returnType)
}?.let { matchingProp ->
targetProp.setter.call(this, matchingProp.getter.call(fromObject))
}
}
}
This approach uses reflection, but it uses Kotlin reflection which is very lightweight. I haven't timed anything, but it should run almost at same speed as copying properties by hand.
Now given 2 classes:
data class DataOne(val propA: String, val propB: String)
data class DataTwo(var propA: String = "", var propB: String = "")
You can do the following:
var data2 = DataTwo()
var data1 = DataOne("a", "b")
println("Before")
println(data1)
println(data2)
// this copies all matching properties
data2.copyPropsFrom(data1)
println("After")
println(data1)
println(data2)
data2 = DataTwo()
data1 = DataOne("a", "b")
println("Before")
println(data1)
println(data2)
// this copies only matching properties from the provided list
// with complete refactoring and completion support
data2.copyPropsFrom(data1, DataOne::propA)
println("After")
println(data1)
println(data2)
Output will be:
Before
DataOne(propA=a, propB=b)
DataTwo(propA=, propB=)
After
DataOne(propA=a, propB=b)
DataTwo(propA=a, propB=b)
Before
DataOne(propA=a, propB=b)
DataTwo(propA=, propB=)
After
DataOne(propA=a, propB=b)
DataTwo(propA=a, propB=)

Passing java object to python

I am prototyping an interface to our application to allow other people to use python, our application is written in java. I would like to pass some of our data from the java app to the python code but I am unsure how to pass an object to python. I have done a simple java->python function call using simple parameters using Jython and found it very useful for what I am trying to do. Given the class below, how can I then use it in Python/Jython as an input to a function/class:
public class TestObject
{
private double[] values;
private int length;
private int anotherVariable;
//getters, setters
}
One solution. You could use some sort of message system, queue, or broker of some sort to serialize/deserialize, or pass messages between python and java. Then create some sort workers/producer/consumers to put work on the queues to be processed in python, or java.
Also consider checking out for inspiration: https://www.py4j.org/
py4j is used heavily by/for pyspark and hadoop type stuff.
To answer your question more immediately.
Example using json-simple.:
import org.apache.commons.io.FileUtils;
import org.json.simple.JSONObject;
//import org.json.simple.JSONObject;
public class TestObject
{
private double[] values;
private int length;
private int anotherVariable;
private boolean someBool;
private String someString;
//getters, setters
public String toJSON() {
JSONObject obj=new JSONObject();
obj.put("values",new Double(this.values));
obj.put("length",new Integer(this.length));
obj.put("bool_val",new Boolean(this.SomeBool));
obj.put("string_key",this.someString);
StringWriter out = new StringWriter();
obj.writeJSONString(out);
return out.toString();
}
public void writeObject(){
Writer writer = new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream("anObject.json"), "utf-8")
)
)
writer.write(this.toJSON());
}
public static void setObject(){
values = 100.134;
length = 12;
anotherVariable = 15;
someString = "spam";
}
}
And in python:
class DoStuffWithObject(object):
def __init__(self,obj):
self.obj = obj
self.changeObj()
self.writeObj()
def changeObj(self):
self.obj['values'] = 100.134;
self.obj['length'] = 12;
self.obj['anotherVariable'] = 15;
self.obj['someString'] = "spam";
def writeObj(self):
''' write back to file '''
with open('anObject.json', 'w') as f:
json.dump(self.obj, f)
def someOtherMethod(self, s):
''' do something else '''
print('hello {}'.format(s))
import json
with open('anObject.json','r') as f:
obj = json.loads(f.read())
# print out obj['values'] obj['someBool'] ...
for key in obj:
print(key, obj[key])
aThing = DoStuffWithObject(obj)
aThing.someOtherMethod('there')
And then in java read back the object. There are solutions that exist implementing this idea (JSON-RPC, XML-RPC, and variants). Depending, you may may also want to consider using something like ( http://docs.mongodb.org/ecosystem/drivers/java/ ) the benefit being that mongo does json.
See:
https://spring.io/guides/gs/messaging-reactor/
http://spring.io/guides/gs/messaging-rabbitmq/
http://spring.io/guides/gs/scheduling-tasks/
Celery like Java projects
Jedis
RabbitMQ
ZeroMQ
A more comprehensive list of queues:
http://queues.io/
Resources referenced:
http://www.oracle.com/technetwork/articles/java/json-1973242.html
How do I create a file and write to it in Java?
https://code.google.com/p/json-simple/wiki/EncodingExamples
Agree with the answer below. I think that the bottom line is that "Python and Java are separate interpreter-environments." You therefore shouldn't expect to transfer "an object" from one to the other. You shouldn't expect to "call methods." But it is reasonable to pass data from one to another, by serializing and de-serializing it through some intermediate data format (e.g. JSON) as you would do with any other program.
In some environments, such as Microsoft Windows, it's possible that a technology like OLE (dot-Net) might be usable to allow environments to be linked-together "actively," where the various systems implement and provide OLE-objects. But I don't have any personal experience with whether, nor how, this might be done.
Therefore, the safest thing to do is to treat them as "records," and to use serialization techniques on both sides. (Or, if you got very adventurous, run (say) Java in a child-thread.) An "adventurous" design could get out-of-hand very quickly, with little return on investment.
You need to make the python file to exe using py2exe , Refer the link : https://www.youtube.com/watch?v=kyoGfnLm4LA. Then use the program in java and pass arguements:
Please refer this link it will be having the details:
Calling fortran90 exe program from java is not executing

Categories