Error in ServiceStack JSON processing under MonoDroid - json

I'm trying to use ServiceStack for Json serialization/deserialization in MonoDroid project.
I've built ServiceStack to run it in MonoDroid environment, but now I have issue with JSON deserialization.
Example code:
public class Track
{
public string Id { get; set; }
public string Title { get; set; }
public string Artist { get; set; }
public string Hash { get; set; }
public string Type { get; set; }
}
}
...
var track = new Track { Id = "1", Artist = "artist name", Hash = "654874", Title = "song title", Type = "mp3", };
var json = ServiceStack.Text.JsonSerializer.SerializeToString(track);
var track1 = ServiceStack.Text.JsonSerializer.DeserializeFromString<Track>(json);
On deserialization I have an exception:
Unhandled Exception:
System.ArgumentNullException: Argument cannot be null.
Parameter name: method
Stacktrace:
[External Code]
0x5E in ServiceStack.Text.Json.JsonReader.GetParseFn at [...]\Android\ServiceStack.Text\src\ServiceStack.Text\Json\JsonReader.Generic.cs:36 C#
0x2 in ServiceStack.Text.Json.JsonTypeSerializer.GetParseFn at [...]\Android\ServiceStack.Text\src\ServiceStack.Text\Json\JsonTypeSerializer.cs:283 C#
0xF in ServiceStack.Text.Common.TypeAccessor.Create at [...]\Android\ServiceStack.Text\src\ServiceStack.Text\Common\DeserializeType.cs:146 C#
0x142 in ServiceStack.Text.Common.DeserializeType`1[[ServiceStack.Text.Json.JsonTypeSerializer, ServiceStack.Text, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].GetParseMethod at [...]\Android\ServiceStack.Text\src\ServiceStack.Text\Common\DeserializeType.cs:60 C#
0x43A in ServiceStack.Text.Common.JsReader`1[[ServiceStack.Text.Json.JsonTypeSerializer, ServiceStack.Text, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].GetParseFn at [...]\Android\ServiceStack.Text\src\ServiceStack.Text\Common\JsReader.cs:100 C#
0x6 in ServiceStack.Text.Json.JsonReader`1[[Database.Models.Track, AssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]..cctor at [...]\Android\ServiceStack.Text\src\ServiceStack.Text\Json\JsonReader.Generic.cs:58 C#
0x1B in ServiceStack.Text.JsonSerializer.DeserializeFromString at [...]\Android\ServiceStack.Text\src\ServiceStack.Text\JsonSerializer.cs:33 C#
As I see there is:
var genericType = typeof(JsonReader<>).MakeGenericType(type);
var mi = genericType.GetMethod("GetParseFn", BindingFlags.Public | BindingFlags.Static);
parseFactoryFn = (ParseFactoryDelegate)Delegate.CreateDelegate(typeof(ParseFactoryDelegate), mi);
genericType is "ServiceStack.Text.Json.JsonReader`1[System.String]"
type is "System.String"
So, there "mi" variable is null
Are any ideas how to fix it, or where to look?
Thanks.

The problem here was that you had linking enabled in your build configuration, and the GetParseFn() method was being linked away, as it wasn't explicitly being referenced.
The linker is a static analysis tool that is included as part of Mono for Android's build process. It will scan through your compiled application and actually strip out any pieces of .NET (or in this case, your compiled ServiceStack class library) that aren't explicitly being referenced. This goes a long way to cut down the size of your application, but you can run into problems, as seen here. Since the GetParseFn() method was never being explicitly referenced (it is being called via reflection), the linker had no idea it was needed and linked it away.
There are several ways you can handle this problem going forward.
Disable linking entirely: you can turn off linking in the project's properties. In general it's easier to leave it off for debug builds, and turn it on for release builds. This obviously isn't a full solution if you ever plan on doing a release build, of course.
Link only SDK assemblies: this option will tell the linker only to operate on the .NET BCL and Android SDKs, and will leave your libraries alone.
Use PreserveAttribute: Using this attribute you can tell the linker to leave in certain pieces that you know are required, even though they're not explicitly referenced. Since ServiceStack is an external library and not your own, this probably isn't the best solution in this case.
Use Linkskip: This option allows you to specify specific assemblies that shouldn't be touched by the linker, allowing you to leave the linker on but simply opt out when needed.
Personally, in your situation here I could suggest going the Linkskip route. It would allow you to still get all the benefits of the linker, but have it ignore ServiceStack to avoid problems like this. In your project file, you would end up with something along the lines of this:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<AndroidLinkMode>Full</AndroidLinkMode>
<AndroidLinkSkip>ServiceStack.Text</AndroidLinkSkip>
</PropertyGroup>

Related

How to write the configuration of a list of objects for a Quarkus extension

I'm writing a Quarkus extension (internal usage) and cannot figure how to correctly write the configuration part.
I need to setup a configuration that looks like this, a list of objects containing several configuration properties.
some:
list-of-config:
- prop1: value1
prop2: value2
prop3: value3
- prop1: value4
prop2: value5
prop3: value6
So i was thinking to use #ConfigGroup and a List<> as in the following example:
#ConfigRoot(name = "some", phase = ConfigPhase.BUILD_TIME)
public class MyConfig {
#ConfigItem(defaultValue = "true")
public boolean enabled;
public List<MyGroup> listOfConfig;
#ConfigGroup
public static class MyGroup {
#ConfigItem
public String prop1;
#ConfigItem
public String prop2;
#ConfigItem
public String prop3;
}
}
Unfortunately i get the following exception when starting the application:
SRCFG00013: No Converter registered for class org....MyConfig$MyGroup
#ConfigGroup works pretty well when they are loaded as a single object, but not as a List. I guess this is not really related to config group itself since i also have this error without using config group but simple objects.
Has anyone already tried to use a list of object as configuration for a Quarkus extension ? The official documentation lacks of example about that.
According to the documentation, any type not being listed or accepting a String parameter as constructor/valueOf/of cannot be used with List or Optional types, except Optional that can also be applied to a configuration group object. Unfortunately, Optional + config group is bugged as mentioned here
So looks like custom objects are not supported, which answer my question.
Quarkus is working in adding the use of config mapping for extensions as well, which should solve the issues and add the support for complex types in the future versions (currently 2.1.0 at the time of this question)

Strongly-Typed Configuration in .NET Core ignores JsonProperty attribute

I've been playing with strongly-typed configuration in .NET Core and I've found some weird behavior.
POCO
public class ModuleConfiguration
{
[JsonProperty("menu")]
public List<MenuItem> MenuItems { get; set; }
}
Settings.json
{
"moduleConfiguration": {
"menu": [
{
"id": 1,
"name": "test"
}
]
}
}
When I load the configuration:
var builder = new ConfigurationBuilder().AddJsonFile(path);
var config = builder.Build().GetSection("moduleConfiguration").Get<T>();
the MenuItems collection is null, but if I change "menu" to "menuItems" (in settings.json), the collection is populated correctly.
Does it mean that JsonProperty attribute is being ignored?
That's not how Microsoft.Extensions.Configuration (and Microsoft.Extensions.Configuration.Json in particular) works. It doesn't use JSON.NET to deserialize the configuration due to the fact that configuration settings can come from different sources, for example xml files, environment variable or command line parameters.
All of these are stored in a dictionary and queried.
For example if you want to access moduleConfiguration.menu via configuration you have to do Configuration["moduleConfiguration:menu"] (note that colon : is used as separator for child objects).
For the reasons named above, annotating the property via [JsonProperty("menu")] won't do anything, because JSON.NET isn't involved in the process and the Attributes are just meta data and do not do anything by themselves.
Also when you observe the source code on GitHub, you will see that it uses the JsonReader and a visitor pattern to populate the dictionary.
That being said: the property in C# and the properties in json (or xml or commandline parameters) must exactly (case insensitive).

Startup.cs error (ASP.Net Core configuration)

I am trying to set up an ASP.Net Core application to read in configuration settings from a json file. I am using VS2015 and .NetCore 1.0 (with .Net Core Tools preview 2). I am having problems getting a simple piece of boiler plate code to compile.
I am using the following code, which was published at
http://asp.net-hacker.rocks/2016/03/21/configure-aspnetcore.html
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();
if (env.IsDevelopment())
{
// This will push telemetry data through Application Insights
// pipeline faster, allowing you to view results immediately.
builder.AddApplicationInsightsSettings(developerMode: true);
}
Configuration = builder.Build();
}
However, the IDE/compiler complains that 'the name "Configuration" does not exist in the current context' (last line of code). The only suggestion from the IDE is to include Microsoft.Extensions.Configuration. However this is a namespace which does not contain an object or property named "Configuration".
In addition 'AddApplicationInsightsSettings' fails with does IConfigurationBuilder not contain a definition for AddApplicationInsightsSettings and no extension method AddApplicationInsightsSettings accepting a first argument of type IConfigurationBuilder could be found
Any suggestions please ?
Thanks
Simply add Configuration property to your Startup class, tutorial has missed this 'step':
public IConfigurationRoot Configuration { get; set; }
ConfigurationBuilder.Build() method just returns instance of IConfigurationRoot, that you should save, if need to get settings further in Startup class (in ConfigureServices method for example).
Regarding second error, looks like you didn't add the Application Insights dependency:
{
"dependencies": {
"Microsoft.ApplicationInsights.AspNetCore": "1.0.0"
}
}

Basic Windsor Constructor Injection

I am new to Windsor and am trying to implement the most basic constructor injection. Apparently the API has changed so much over the recent versions that the documentation that is for the current version seems to assume you already know how to do it, and the documentation for the old versions is outdated.
I have a simple test component:
public class ConstructorInjectedComponent
{
public IMyComponent Component { get; set; }
public ConstructorInjectedComponent(IMyComponent component)
{
Component = component;
}
}
There is a simple implementation of IMyComponent:
public class AMyComponent : IMyComponent
{
public string Name { get; set; }
public AMyComponent()
{
Name = Guid.NewGuid().ToString("N");
}
}
And I want to somehow register my types with Windsor such that I can get back an instance of ConstructorInjectedComponent that contains an instance of its dependency: IMyComponent.
I've register AMyComponent like so:
_container.Register(Component.For(typeof(AMyComponent)));
I've register ConstructorInjectedComponent like this:
_container.Register(Component.For(typeof(ConstructorInjectedComponent)));
and tried to resolve it with
_container.Resolve(typeof(ConstructorInjectedComponent));
But that fails with "can't create component ConstructorInjectedComponent because it has dependencies which need to be satisfied.
so I try to pass in an IDictionary of dependencies for the ConstructorInjectedComponent ... and this is where the documentation fails me.
I have no idea how to define that dictionary. I can find no documentation which explains it. I've tried this:
var d = new Dictionary<string, string>() {{"IMyComponent", "AMyComponent"}};
_container.Register(Component.For(typeof(ConstructorInjectedComponent))
.DependsOn(dependencies));
But that fails with the same "has dependencies that need to be resolved" error.
What am I doing wrong?
First it's crucial to make sure you understand the basic concepts, namely what a component is, what a service is, and what a dependency is.
The documentation about it is quite good.
The documentation about how to use registration API should help you get going.
The tl;dr asnwer is: since ConstructorInjectedComponent depends on IMyComponent make sure you register AMyComponent to expose IMyComponent as a service.
_container.Register(Component.For<IMyComponent>().ImplementedBy<AMyComponent>());

Jibx always gives "Error during validation: null"

I'm really stumped on this incredibly simple mapping. It looks just like one of the examples even. If I comment out the internal structure, it'll run the binding compiler successfully. If I put the internal structure back in, it fails. Note that the internal structure is just defining the XML. This is basically example5 of the JIBX tutorial examples.
<binding>
<mapping name="RequestTransaction" class="TransactionRequest">
<value name="version" set-method="setVersion" get-method="getVersion" style="attribute" />
<structure name="transHeader">
<value name="requestCount" set-method="setRequestCount" get-method="getRequestCount"/>
</structure>
</mapping>
<binding>
Then I get the following error on the jibx compile:
Error: Error during validation: null; on mapping element at (line 2, col 97, in jibx-binding.xml)
I'm absolutely stumped and out of ideas. Google shows nothing useful.
The <structure> is arguably the most important concept in JiBX binding because it allows you to map arbitrary XML to your Java classes without forcing you to create bloated and ugly layers of nested Java objects and classes to match the XML design.
In this case your binding declares that you have an XML element named <transHeader> that will not be present in your Java class.
With some slight fixes to your XML format, your binding works perfectly. I assume the fact that your binding has two <binding> open tags rather than and open and close <binding></binding> is a typo, because you said you got it to work without the structure. Also add <?xml version="1.0"?> at the top of your binding file. Those two XML mods allow the JiBX 1.2 binding compiler to work with the following Java class:
(Note: you didn't provide the Java class this binding is for so I had to reconstruct it from the info you put in the binding file. The obvious side effect of this is that I reconstructed a class that will work with this binding. But the simple fact is that a JiBX binding by design contains all the info you need to know about the class and the XML.)
public class TransactionRequest {
private String version;
private int requestCount;
public void setVersion(String ver) {
version = ver;
}
public String getVersion() {
return version;
}
public void setRequestCount(int count) {
requestCount = count;
}
public int getRequestCount() {
return requestCount;
}
}
compile the class then run the binding compiler with:
>java -jar jibx-bind.jar jibx-binding.xml
To test it I used the following sample.xml:
(Note: you also didn't provide the XML you are trying to map so again I created a sample based on what you did provide)
<?xml version="1.0"?>
<RequestTransaction version="0.1">
<transHeader>
<requestCount>3</requestCount>
</transHeader>
</RequestTransaction>
Running the test uses the following code:
public static void main(String[] argz) {
String fileName = "./sample.xml";
IBindingFactory bfact = null;
IUnmarshallingContext uctx = null;
TransactionRequest sample = null;
try {
bfact = BindingDirectory.getFactory(TransactionRequest.class);
uctx = bfact.createUnmarshallingContext();
InputStream in = new FileInputStream(fileName);
sample = (TransactionRequest)uctx.unmarshalDocument(in, null);
System.out.println(sample.getRequestCount());
System.out.println(sample.getVersion());
}
catch (Exception e) {
e.printStackTrace();
}
}
And it runs successfully.
It's been a while now, but I found it was related to inheritance. I needed to give mappings for everything in the inheritance tree, including interfaces as I recall.
I ended up creating a wrapper object, which I've found seems to be the easiest way to use JIBX in general. Trying to map a true domain class causes tendrils into every class that class touches and I have to unjar everything so JIBX can find the classes, including 3rd party libs.