Redstone mapper with flutter - dart

I want to use the redstone mapper to decode Json to objects.
However flutter doesn't support mirrors and so I cannot initialize the mapper over the normal way with bootstrapMapper();
Therefore I looked it up, I have to use staticBootstrapMapper(...)
/**
* initialize the mapper system.
*
* This function provides a mapper implementation that
* uses data generated by the redstone_mapper's transformer,
* instead of relying on the mirrors API.
*
*/
void staticBootstrapMapper(Map<Type, TypeInfo> types) {
_staticTypeInfo = types;
configure(_getOrCreateMapper, _createValidator);
}
Link to source code
I dont know what I should put into the map of Map<Type, TypeInfo> types.
Lets say I want to use ObjectData to transform json data to this object.
But how do I have to use this initializing method? Unfortunately I didnt find an example how to use this static bootstrap manager.
class ObjectData {
#Field()
#NotEmpty()
DataType dateType; // might be a User object
#Field()
#NotEmpty()
String id;
#Field()
#NotEmpty()
List<String> versions;
}

Mirrors isn't supported in Flutter, as noted above in comments.
You might want try alternative packages that don't rely on mirrors:
https://pub.dartlang.org/packages/json_serializable
https://pub.dartlang.org/packages/built_value
Of those two (and others) json_serializable looks like the easiest to get started, but might not have as many features.

Related

is it possible to serial object to json in one function in dart

In Java, we can serial any object like this:
Object anyObj = new Object();
String json = JSON.tostring(anyObj);
but in Dart, we must define toJson method like this in every single Object:
import 'dart:convert';
String toJson() => json.encode(toMap());
and define toMap:
Map<String, dynamic> toMap() => {}
any simple way? Image if the system has 10000+ objects, are we write toJson function for every object? Is it possible to serial object to json like Java way in Dart?
Most Java libraries that provide serialization of arbitrary objects rely on runtime reflection to know what fields are present on an object (and their types, etc).
Runtime reflection is technically possible in Dart (using dart:mirrors) but the library is unstable and is not available on all platforms (notably runtime reflection is disabled in Flutter).
The idiomatic Dart way to do this is with code generation. In general, you add the required annotations/etc, then run flutter pub run build_runner build to use the build_runner package to generate extra code.
A couple of popular libraries are:
json_serializable is useful if you have a model class that you want to add toJson() and fromJson() methods to:
#JsonSerializable // marks the class for json code generation
class Dog {
final String name;
final int age;
Dog(this.name, this.age);
// boilerplate for generated implementations
Map<String, dynamic> toJson() => _$DogToJson(this);
factory Dog.fromJson(Map<String, dynamic> json) => _$DogFromJson(json);
}
built_value is a more all-encompassing approach. The main purpose of the library is to provide deep immutability for model classes, similar to Kotlin's data class. However, it also provides good serialization support out of the box. There is a fair amount of boilerplate, but it can definitely be worth it (especially if you use the vscode plugin to write it for you):
abstract class Dog extends Built<Dog, DogBuilder> {
Dog._();
factory Dog([void Function(DogBuilder) updates]) = _$Dog;
String get name;
int get age;
}
You can then use this code like:
final dog = Dog((b) {
b.name = 'name';
b.age = 123;
});
final helloDog = dog.rebuild((b) => b.name = 'hello');
This blog post goes through serialization in detail: https://medium.com/dartlang/darts-built-value-for-serialization-f5db9d0f4159#.h12y94wu7
Both libraries are maintained by Google

log4j2 and custom key value using JSONLayout

I would like to add to my log a String key and an Integer value using Log4j2.
Is there a way to do it? when I added properties to the ThreadContext I was able to add only String:String key and values but this does not help I have numbers that I need to present in Kibana (some graphs)
thanks,
Kobi
The built-in GelfLayout may be useful.
It's true that the default ThreadContext only supports String:String key-values. The work done in LOG4J2-1648 allows you to use other types in ThreadContext:
Tell Log4j to use a ThreadContext map implementation that implements the ObjectThreadContextMap interface. The simplest way to accomplish this is by setting system property log4j2.garbagefree.threadContextMap to true.
The standard ThreadContext facade only has methods for Strings, so you need to create your own facade. The below should work:
public class ObjectThreadContext {
public static boolean isSupported() {
return ThreadContext.getThreadContextMap() instanceof ObjectThreadContextMap;
}
public static Object getValue(String key) {
return getObjectMap().getValue(key);
}
public static void putValue(String key, Object value) {
getObjectMap().putValue(key, value);
}
private static ObjectThreadContextMap getObjectMap() {
if (!isSupported()) { throw new UnsupportedOperationException(); }
return (ObjectThreadContextMap) ThreadContext.getThreadContextMap();
}
}
It is possible to avoid ThreadContext altogether by injecting key-value pairs from another source into the LogEvent. This is (briefly) mentioned under Custom Context Data Injectors (http://logging.apache.org/log4j/2.x/manual/extending.html#Custom_ContextDataInjector).
I found default log4j2 implementation somewhat problematic for passing custom fields with values. In my opinion current java logging frameworks are not well suited for writing structured log events
If you like hacks, you can check https://github.com/skorhone/gelfj-alt/tree/master/src/main/java/org/graylog2/log4j2 . It's a library written for gelf. One of provided features is a layout (ExtGelfjLayout) that supports extracting custom fields (See FieldExtractor) from events. But... im order to send such event, you need to write your own logging facade on top of log4j2.

IBM Integration Bus: How to read user defined node (Java) complex (table) property in Java extension code

I created Java user defined node in IntegrationToolkit (9.0.0.1) and assigned it with several properties. Two of the node properties are simple (of String type) and one property is complex (table property with predefined type of User-defined) that is consisted of another two simple properties.
By following the documentation I was able to read two simple properties in my Java extension class (that extends MbNode and implements MbNodeInterface) by making getters and setters that match the names of the two simple properties. Documentation also states that getters and setters should return and set String values whatever the real simple type of a property may be. Obviously, this would not work for my complex node property.
I was also able to read User Defined Properties that are defined on the message flow level, by using CMP (Integration Buss API) classes, which was another impossible thing to do from user defined node without CMP. At one point I began to think that my complex property would be among User Defined Properties, (although UDPs are defined on the flow level and my property is defined on the custom node level) based on some other random documentation and some other forum discussion.
I finally deduced that the complex property should map to MbTable type (as it is so stated in that type's description), but I was not able to use that.
Does anyone know how to access user defined node's complex(table) property value from Java?
I recently started working with WebSphere Message Broker v 8.0.0.5 for one of my projects and I was going to ask the same question until SO suggested your question which answered my question. It might be a little late for this question but it may help others having similar questions.
After many frustrating hours consulting IBM documentation this is what I found following your thread:
You're correct about the properties being available as user-defined properties (UDP) but only at the node level.
According to the JavaDoc for MbTable class (emphasis added to call out the relevant parts):
MbTable is a complex data type which contains one or more rows of simple data types. It structure is very similar to a * standard java record set. It can not be constructed in a node but instead is returned by the getUserDefinedAttribute() on the MbNode class. Its primary use is in allowing complex attributes to be defined on nodes instead of the normal static simple types. It can only be used in the runtime if a version of the toolkit that supports complex properties is being used.
You have to call com.ibm.broker.plugin.MbNode.getUserDefinedAttribute which will return an instance of com.ibm.broker.plugin.MbTable. However, the broker runtime doesn't call any setter methods for the complex attributes during the node initialization process like it does for simple properties. Also, you cannot access the complex attributes in either the constructor or the setter methods of other simple properties in the node class. These are available only in the run or evaluate method.
The following is the decompiled method definition of com.ibm.broker.plugin.MbNode.getUserDefinedAttribute.
public Object getUserDefinedAttribute(String string) {
Object object;
String string2 = "addDynamicTerminals";
if (Trace.isOn) {
Trace.logNamedEntry((Object)this, (String)string2);
}
if ((object = this.getUDA(string)) != null && object.getClass() == MbElement.class) {
try {
MbTable mbTable;
MbElement mbElement = (MbElement)object;
object = mbTable = new MbTable(mbElement);
}
catch (MbException var4_5) {
if (Trace.isOn) {
Trace.logStackTrace((Object)this, (String)string2, (Throwable)var4_5);
}
object = null;
}
}
if (Trace.isOn) {
Trace.logNamedExit((Object)this, (String)string2);
}
return object;
}
As you can see it always returns an instance of MbTable if the attribute is found.
I was able to access the complex attributes with the following code in my node definition:
#Override
public void evaluate(MbMessageAssembly inAssembly, MbInputTerminal inTerminal) throws MbException {
checkUserDefinedProperties();
}
/**
* #throws MbException
*/
private void checkUserDefinedProperties() throws MbException {
Object obj = getUserDefinedAttribute("geoLocations");
if (obj instanceof MbTable) {
MbTable table = (MbTable) obj;
int size = table.size();
int i = 0;
table.moveToRow(i);
for (; i < size; i++, table.next()) {
String latitude = (String) table.getValue("latitube");
String longitude = (String) table.getValue("longitude");
}
}
}
The documentation for declaring attributes for user-defined extensions in Java is surprisingly silent on this little bit of detail.
Please note that all the references and code are for WebSphere Message Broker v 8.0.0 and should be relevant for IBM Integration Bus 9.0.0.1 too.

How to share data structures with Polymer on both client and server

Problem:
I have a dart file defining some data structures, which I need to use both for the client and for the server. I'd like to make these data structures observable with Polymer. However, the server cannot include the file because of Polymer, because Polymer includes dart:html.
Context:
I am working on a client/server (REST-full) application, where I want the server to provide the data structures defined available as resources. The client should display these resources, and have the possibility to send the modifications to the server. For that, Polymer is invaluable.
The reason I want to have this library available for the server is that I want the server to be able to validate the resources to be stored.
Possible solutions:
I don't yet know the internals of Polymer enough, but if my data structures could inherit from Map, I could use toObservable in the client side code to make the data structure observable, but instead of accessing by dot notation, I'd have to access members by keys instead, making it rather fragile.
I was wondering if I could use mirrors.dart to add the observable annotation on the client.
Of course, managing duplicate code, is really not a solution.
You can use the observe package.
With ChangeNotifier you initiate the change notification yourself by calling notifyPropertyChange when a value changes. The changes get delivered synchronously.
Observable needs dirtyCheck() to be called to deliver changes.
Polymer calls Observable.dirtyCheck() repeatedly to get the changes automatically.
an example for each
import 'package:observe/observe.dart';
class Notifiable extends Object with ChangeNotifier {
String _input = '';
#reflectable
get input => _input;
#reflectable
set input(val) {
_input = notifyPropertyChange(#input, _input, val + " new");
}
Notifiable() {
this.changes.listen((List<ChangeRecord> record) => record.forEach(print));
}
}
class MyObservable extends Observable {
#observable
String counter = '';
MyObservable() {
this.changes.listen((List<ChangeRecord> record) => record.forEach(print));
}
}
void main() {
var x = new MyObservable();
x.counter = "hallo";
Observable.dirtyCheck();
Notifiable notifiable = new Notifiable();
notifiable.input = 'xxx';
notifiable.input = 'yyy';
}

Is there anything like "CheckSum" in Dart (on Objects)?

For Testing purposes I'm trying to design a way to verify that the results of statistical tests are identical across versions, platforms and such. There are a lot things that go on that include ints, nums, dates, Strings and more inside our collections of Objects.
In the end I want to 'know' that the whole set of instantiated objects sum to the same value (by just doing something like adding the checkSum of all internal properties).
I can write low level code for each internal value to return a checkSum but I was thinking that perhaps something like this already exists.
Thanks!
_swarmii
This sounds like you should be using the serialization library (install via Pub).
Here's a simple example to get you started:
import 'dart:io';
import 'package:serialization/serialization.dart';
class Address {
String street;
int number;
}
main() {
var address = new Address()
..number = 5
..street = 'Luumut';
var serialization = new Serialization()
..addRuleFor(address);
Map output = serialization.write(address, new SimpleJsonFormat());
print(output);
}
Then depending on what you want to do exactly, I'm sure you can fine tune the code for your purpose.

Resources