vendredi 12 janvier 2024

How to resolve JAR conflicts with maven-shade-plugin

I have two projects: jartest and jarprj. jartest depends on poi 3.17, whereas jarprj depends on poi 5.10. jartest encounters an error when dynamically loading jarprj. The error message is as follows:

java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.example.App.main(App.java:27)
Caused by: java.lang.NoSuchMethodError: org.apache.poi.xwpf.usermodel.XWPFDocument.getDocComments()Lorg/apache/poi/xwpf/usermodel/XWPFComments;
    at org.example.JarClass.test(JarClass.java:10)
    ... 5 more

The issue may stem from a conflict between the versions of poi. I attempted to rename poi using the maven-shade-plugin, but the error persists. The error message is as follows:

java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.example.App.main(App.java:27)
Caused by: java.lang.NoSuchFieldError: Factory
    at shade.org.apache.poi.xwpf.usermodel.XWPFDocument.onDocumentCreate(XWPFDocument.java:304)
    at shade.org.apache.poi.xwpf.usermodel.XWPFDocument.<init>(XWPFDocument.java:149)
    at org.example.JarClass.test(JarClass.java:9)
    ... 5 more

jartest cannot upgrade its poi version, while jarprj requires poi 5.1.0. What methods are there to solve this? How can we resolve it using maven-shade-plugin?





mercredi 10 janvier 2024

lambdametafactory creation is quite slow compared to just using lambda

@Benchmark
public void testLambdaGeneration(Blackhole bh) {
    Function<Object, Object> function = a -> {
        if(a instanceof Alpha alpha) {
            return alpha.primitiveInt();
        }else {
            throw new RuntimeException();
        }
    };
    bh.consume(function);
}

@Benchmark
public void testManualGeneration(Blackhole bh) {
    try{
        MethodHandle mh = MethodHandles.lookup().findVirtual(Alpha.class, "primitiveInt", MethodType.methodType(int.class));
        MethodType type = mh.type();
        type = type.changeReturnType(Integer.class);
        CallSite callSite = LambdaMetafactory.metafactory(MethodHandles.lookup(),
                "apply",
                MethodType.methodType(Function.class),
                type.erase(), mh, type);
        Function<Object, Object> f = (Function<Object, Object>) callSite.getTarget().invokeExact();
        bh.consume(f);
    }catch (Throwable e) {
        throw new RuntimeException("Unreached");
    }
}

I want to use lambdametafactory to create constructor, getter and setter methods for reflection usage, and generated Function<> is just as fast as the direct call, which greatly satisfies my needs. However, when I use the above code to test the generation performance between lambdafactory and pure lambda, the result is quite unpromising:

LambdaTest.testLambdaGeneration  avgt   50      0.574 ±     0.015  ns/op
LambdaTest.testManualGeneration  avgt   50  29424.815 ± 20402.801  ns/op

I think the lambda function would use LambdaMetafactory internally, so the result should be consistent, but the actual result really shock me.

Is there any thing wrong with my code? How could I improve the LambdaMetafactory.metafactory()'s performance to match the pure lambda generation?





why always i have who add the time package on diverse progamming languages? [closed]

It's always strange to me to have to import the time package into the code, something that in my opinion is so important and basic that it's not directly included without being imported from.

Python sample:

import time time.sleep(1)


I see this in almost all programming languages. I want to understand why this happens, if it does, I'm trying to increase my general understanding of programming.

Ps: Thanks to everyone who wants to help by answering me!

I hope to learn a little more!





mercredi 13 décembre 2023

How to match typeof(

I'm using reflection to determine how to format properties on an object.

Here's a dictionary of formatters:

var formatters = new Dictionary<Type, Func<object, object>>()
{
    { typeof(Enum), x => ((Enum)x)?.FormatEnum() },
    { typeof(DateTime?), x => ((DateTime?)x)?.ToShortDateString() },
    { typeof(string), x => x.ToString().ToLower() }
};

Most types will work fine, however when I get the type of my nullable enum TaskStatus, the type is not "Enum", it's the name of the type.

I noticed the base type is "Enum", however I don't want to have to check the base type since most other types will work just fine with the type.

For example, checking the type of string works fine:

typeof(string).FullName = "System.String"

But for the TaskStatus enum:

typeof(Enums.TaskStatus).FullName = "Enums.TaskStatus"

So typeof(Enum) != typeof(Enums.TaskStatus) which is what is preventing the dictionary from finding a match.

Is there any way to find a match in the formatters dictionary without having to put in all the different nullable enum type names I am using?

Edit:

Here's my entire code:

public class NoteHistory
{
    [JsonProperty("Status")]
    public TaskStatus? TaskStatus { get; set; }
    [JsonProperty("CreatedDate")]
    public DateTime? CreatedDate { get; set; }
    [JsonProperty("Description")]
    public string Description { get; set; }
    public bool IsDeleted { get; set; } // not interested in comparing this
}

public enum TaskStatus
{
    ToDo,
    Done
}

public static void DisplayValues()
{
    var noteHistory1 = new NoteHistory
    {
        TaskStatus = TaskStatus.ToDo
    };

    var noteHistory2 = new NoteHistory
    {
        TaskStatus = TaskStatus.Done
    };

    // Get all properties with JsonProperty attr.
    var propertiesToCompare = typeof(NoteHistory)
        .GetProperties()
        .Where(x => x.CustomAttributes
            .Any(y => y.AttributeType.Name == nameof(JsonPropertyAttribute)));

    var comparers = new Dictionary<Type, Func<object, object, bool>>
    {
        { typeof(string), (x, y) => !string.Equals(x?.ToString(), y?.ToString(), StringComparison.InvariantCultureIgnoreCase) }
    };

    var formatters = new Dictionary<Type, Func<object, object>>()
    {
        { typeof(Enum), x => ((Enum)x)?.FormatEnum() }, // doesn't work
        { typeof(DateTime?), x => ((DateTime?)x)?.ToShortDateString() },
        { typeof(string), x => x.ToString().ToLower() },
    };

    foreach (var propertyToCompare in propertiesToCompare)
    {
        var prop1Value = propertyToCompare.GetValue(noteHistory1);
        var prop2Value = propertyToCompare.GetValue(noteHistory2);

        Func<object, object, bool> comparer;
        comparers.TryGetValue(propertyToCompare.PropertyType, out comparer);

        var hasChanged = comparer?.Invoke(prop1Value, prop2Value) ?? prop1Value != prop2Value;

        if (hasChanged)
        {
            Func<object, object> formatter;
            formatters.TryGetValue(propertyToCompare.PropertyType, out formatter);

            var formattedValue = formatter?.Invoke(noteHistory2);
            // TODO: display the value
        }
    }
}




mardi 5 décembre 2023

Cannot always get reflect info for func signature in Go

I have this which returns a string representation of a function signature:

func getFuncSignature(v interface{}) string {

    funcValue := reflect.ValueOf(v)
    funcType := funcValue.Type()
    name := funcType.Name()

    // Function signature
    var params []string
    for i := 0; i < funcType.NumIn(); i++ {
        nm := funcType.In(i).Name()
        if strings.TrimSpace(nm) == "" {
            nm = "<unk>"    // <<<<<<<<<<<<<<<<<<<<< HERE 1
        }
        params = append(params, nm)
    }

    var returns []string
    for i := 0; i < funcType.NumOut(); i++ {
        nm := funcType.Out(i).Name()
        if strings.TrimSpace(nm) == "" {
            nm = "<unk>"  // <<<<<<<<<<<<<<<<<<<<<< HERE 2
        }
        returns = append(returns, nm)
    }

    paramsStr := strings.Join(params, ", ")
    returnsStr := strings.Join(returns, ", ")

    if name != "" {
        return fmt.Sprintf("(func %s(%s) => (%s))", name, paramsStr, returnsStr)
    }

    return fmt.Sprintf("(func(%s) => (%s))", paramsStr, returnsStr)
}

however, some parameter and return types return empty strings, so I put in "" which isn't really ideal. Is there some way to retrieve the names/types of the input and return values?





lundi 4 décembre 2023

C#: how to check if a property type is string? (nullable string) or string [duplicate]

giving this code:

var t = typeof(Sample);
var p1 = t.GetProperty(nameof(Sample.Str1));
var p2 = t.GetProperty(nameof(Sample.Str2));

Console.WriteLine(p1!.PropertyType == p2!.PropertyType);

public class Sample
{
    public string Str1 { get; set; } = default!;
    public string? Str2 { get; set; }
}

in a dotnet project with <Nullable>enable</Nullable> in csproj it prints "True"

but using int instead of string it shows "False".

Is there any way to know if the propertyType is the source code is "string" or "string?" ?





C# Merge Null Or Not Existing Properties and its properties from strongly typed Model after deserialization

The problem is I have a config which I can update using my Model, I deploy new update and user won't get updated configuration file, so it will cause null reference exception, etc. Now I just set default values or use new() to make it at least similar to latest configuration value, but its a hell, I need to always support it, what if I'll or someone else even forget to merge null properties?

I have 3 different config files (YAML, XML, JSON),but with single one model. I want it to merge all null properties, arrays of the arrays, not existing items of the array from default config into existing config, properties of the properties, etc, however I want to save all existing things from the deserialized config.

My Model:

[Serializable]
public class GuardSettings
{
    public GuardSettings()
    {
    }

    public UnturnedGuardOptions UnturnedGuardOptions { get; set; }
    public UnturnedIntegrityVault UnturnedIntegrityVault { get; set; }
    public LocalTimeOptions LocalTimeOptions { get; set; }
    [YamlIgnore, XmlIgnore] public VanillaOptions VanillaOptions { get; set; }
    public LogReport LogReport { get; set; }
    public DiscordWebhookLaunch DiscordWebhookLaunch { get; set; }
    public DiscordWebhookReject DiscordWebhookReject { get; set; }
    public DiscordWebhookAccept DiscordWebhookAccept { get; set; }
    public DiscordWebhookCancel DiscordWebhookCancel { get; set; }
    public DiscordWebhookReport DiscordWebhookReport { get; set; }
    public DiscordWebhookBans DiscordWebhookBans { get; set; }
    public DiscordWebhookUnbans DiscordWebhookUnbans { get; set; }
    public DatabaseOptions DatabaseOptions { get; set; }
    public UnturnedPanelIntegration UnturnedPanelIntegration { get; set; }
    public BanOptions BanOptions { get; set; }
    public PlayerWhitelist PlayerWhitelist { get; set; }
    public HWIDHistory HWIDHistory { get; set; }
    [YamlMember(Alias = "tpsOptions")] public TPSOptions TPSOptions { get; set; }
    public FeaturesOptions FeaturesOptions { get; set; }
    public Feature[] Features { get; set; }
}

[Serializable]
public class Feature
{
    public Feature()
    {
    }

    public string Name { get; set; } = string.Empty;
    public bool Enabled { get; set; }
    public Argument[] Arguments { get; set; } = Array.Empty<Argument>();
}

[Serializable]
public class Argument
{
    public Argument()
    {
    }

    public string? Name { get; set; }
    public object? Value { get; set; }
}

This is how I see it, I have default settings just using my custom factory that configures default config with all properties (in a proper way), and the existing settings is a deserialized config from file (YAML, XML or JSON).

private static GuardSettings Merge(GuardSettings defaultSettings, GuardSettings existingSettings)

After that I want to serialize the Merged config to let configuration being updated, so user can change newest properties and be up to date with changes in the config!

I tried to use Reflection and AutoMapper, but with no success.