GithubHelp home page GithubHelp logo

Comments (7)

raphw avatar raphw commented on July 1, 2024

Calling withoutCode creates an abstract method and a constructor cannot be abstract. Instead, you would need to call the Object class's default constructor. For this, you would need to implement approriate byte code. You can do this by creating a simple Instrumentation:

TypeDescription objectType = new TypeDescription.ForLoadedType(Object.class);
new Instrumentation.Simple(
  MethodVariableAccess.forType(objectType).loadFromIndex(0), 
  MethodInvocation.invoke(objectType.getDeclaredMethods().filter(isConstructor()).getOnly())
    .special(objectType),
  MethodReturn.VOID);

I recognize this use case and that this should be easier. I will add a utility instrumentation that makes this a one-liner in the future.

Also, you might want the type itself to be public what you did not specify.

from byte-buddy.

uvwild avatar uvwild commented on July 1, 2024

Thanks mate. It was working in the end:
Find all annotated classes:

    public static Set<Constructor> getSQLInjectedItemSubClassCtors() {
        Predicate<String> filter = new FilterBuilder().include("mycore.legacy.*")
                                                    .include("myother.legacy.core.*");
        Reflections reflections = new Reflections(new ConfigurationBuilder().filterInputsBy(filter)
                             .setScanners(
                                   new SubTypesScanner().filterResultsBy(filter), 
                                   new MethodAnnotationsScanner().filterResultsBy( filter), 
                                   new MethodParameterScanner()).setUrls( ClasspathHelper.forClassLoader()));
        Set<Constructor> annotated = reflections.getConstructorsAnnotatedWith(SQLInject.class);
        return annotated;
    }

Then create the mixin for them:

    public static Class<?> createMixinFor(final Class declaringClass) {
        assert(declaringClass != null);
        try {
            Annotation methodAnnotation = JacksonItemMixin.class.getDeclaredConstructor(Long.class).getAnnotation(JsonCreator.class);
            assert(methodAnnotation != null);
            Annotation parameterAnnotation = JacksonItemMixin.class.getDeclaredConstructor(Long.class).getParameterAnnotations()[0][0];
            assert(parameterAnnotation != null);
            LOG.debug("Annotation: {}",parameterAnnotation.annotationType());
            TypeDescription objectType = new TypeDescription.ForLoadedType(Object.class);
            Instrumentation instrumentation = new Instrumentation.Simple(MethodVariableAccess.forType(objectType).loadFromIndex(0), MethodInvocation.invoke(
                objectType.getDeclaredMethods().filter(ElementMatchers.isConstructor()).getOnly()).special(objectType), MethodReturn.VOID);
            Class<?> dynamicType = new ByteBuddy().withModifiers(TypeManifestation.ABSTRACT)
                                                  .subclass(Object.class, ConstructorStrategy.Default.NO_CONSTRUCTORS)
                                                  .name(declaringClass.getCanonicalName().concat("MixIn"))
                                                  .defineConstructor(Arrays.<Class<?>>asList(Long.class), Visibility.PROTECTED)
                                                  .intercept(instrumentation)
                                                  .annotateMethod(methodAnnotation)
                                                  .annotateParameter(0, parameterAnnotation)
                                                  .make()
                                                  .load(CachingItemFactory.class.getClassLoader(), ClassLoadingStrategy.Default.CHILD_FIRST_PERSISTENT)
                                                  .getLoaded();
            LOG.debug("created Mixin {} for {}", dynamicType, declaringClass);
            assert(dynamicType.getDeclaredConstructor(Long.class) != null);
            assert(dynamicType.getDeclaredConstructor(Long.class).getAnnotation(JsonCreator.class) != null);
            assert(dynamicType.getDeclaredConstructor(Long.class).getParameterAnnotations()[0][0] != null);
            return dynamicType;
        } catch (NoSuchMethodException nme) {
            LOG.error("createMixinFor: ", nme);
        }
        return null;
    }

Finally, use jackson mapper to apply this all:

        objectMapper = new ObjectMapper();
        // use generated Mixin Classes
        Set<Constructor> ctors = getSQLInjectedItemSubClassCtors();
        for (Constructor ctor : ctors) {
            // add mixin annotations for inheritance relationships
            Class<?> persistenceClass = ctor.getDeclaringClass();
            objectMapper.addMixInAnnotations(persistenceClass, createMixinFor(persistenceClass));
        }

from byte-buddy.

raphw avatar raphw commented on July 1, 2024

Great, I would like to keep this issue open until I had the time to implement an instrumentation that makes this impler. Thanks for reporting and providing feedback.

from byte-buddy.

uvwild avatar uvwild commented on July 1, 2024

Oops sorry didn't want to disturb your work flow....

from byte-buddy.

raphw avatar raphw commented on July 1, 2024

No worries. I appreciate the clean-up and the feedback. This just serves me as a reminder.

from byte-buddy.

raphw avatar raphw commented on July 1, 2024

I implemented a MethodCall instrumentation that is included in the next version of Byte Buddy. You can then create the instrumentation by:

MethodCall.invoke(Object.class.getDeclaredConstructor())

This instrumentation also allows you to hand over parameters if you wanted to call a constructor that takes parameters.

from byte-buddy.

raphw avatar raphw commented on July 1, 2024

This instrumentation is now implemented in the latest version and pushed to Maven Central.

from byte-buddy.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.