Constructor ITD question: introduce no-arg ctor instead of letting JDO/JPA enhancer do it?

View: New views
3 Messages — Rating Filter:   Alert me  

Constructor ITD question: introduce no-arg ctor instead of letting JDO/JPA enhancer do it?

by matthewadams12 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I'm having some trouble getting around a problem I'm having with field
initialization and a persistence enhancer (OpenJPA's, but any JDO or
JPA enhancer will suffer this problem).  The build process is to first
compile with ajc, then enhance, which adds a no-arg constructor.
Problem is, since the enhancer adds the constructor **after** ajc
compilation, introduced fields are not initialized.

Is there a way to introduce a constructor to any class with a given
annotation that doesn't already have a no-arg constructor of any
visibility such that field initialization takes place?  This would
prevent the enhancer from adding a no-arg constructor after aspect
compilation.

JPA Example where a UUID field is being introduced with its field
initialization inlined:

=====================
@Entity
public class Foo {
    @Id protected Long id;
    // ...
}
=====================
public interface HasUuid { UUID getUuid(); }
=====================
public aspect HasUuidMixin {
    public static interface Intro extends HasUuid {}
    declare parents:  (@Entity *) implements Intro;
    private UUID Intro.uuid = UUID.randomUUID();
    public UUID Intro.getUuid() { return uuid; }
}
=====================
// DOES NOT COMPILE
public aspect NoArgConstructorMixin {
    public ((@Entity *) && !hasmethod(* new())).new() { // can't
introduce constructors with this syntax
        // how do I ensure fields are initialized in here?  call super()?
    }
}
=====================

Thanks,
Matthew
_______________________________________________
aspectj-users mailing list
aspectj-users@...
https://dev.eclipse.org/mailman/listinfo/aspectj-users

Re: Constructor ITD question: introduce no-arg ctor instead of letting JDO/JPA enhancer do it?

by Simone Gianni-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Matthew,


Matthew Adams wrote:

> =====================
> // DOES NOT COMPILE
> public aspect NoArgConstructorMixin {
>     public ((@Entity *) && !hasmethod(* new())).new() { // can't
> introduce constructors with this syntax
>         // how do I ensure fields are initialized in here?  call super()?
>     }
> }
> =====================
>  

you cannot use type patterns when declaring an ITD. The syntax of ITD
expects a simple type, not a pattern.

So you can write :

public String SomeClass.toString() { ... }

But you cannot write :

public String ((@Entity *)).toString() { ... }

Instead you have to do as you have already done with the Intro interface
: declare an empty marker interface, then tell AspectJ to inject methods
to that interface, then use declare parents to place the interface using
a type pattern.

You should be able to declare also constructors this way.

I'm also using ApsectJ + OpenJPA enhancer, and I'm not facing the
problem this problem, but probably I don't have fields initialized
calling a static method. Since OpenJPA enhances the class AFTER ajc (for
me too), it should see all the fields and methods that ajc has added to
the entity classes correctly (it surely does for property).

If the OpenJPA introduced constructor does not take into account the
fields added by AspectJ then maybe you're hitting a bug in the OpenJPA
enhancer.

Hope this helps,
Simone

--
Simone Gianni            CEO Semeru s.r.l.           Apache Committer
http://www.simonegianni.it/

_______________________________________________
aspectj-users mailing list
aspectj-users@...
https://dev.eclipse.org/mailman/listinfo/aspectj-users

Re: Constructor ITD question: introduce no-arg ctor instead of letting JDO/JPA enhancer do it?

by matthewadams12 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Simone,

I'm aware of the fact that you can't use type patterns when declaring
an ITD.  I had already tried injecting a no-arg constructor to a
marker interface and using declare parents, and that didn't work.  The
aspect I tried is:

import javax.persistence.Entity;
public aspect NoArgConstructorMixin {
        public static interface HasNoArgConstructor {}
        declare parents : ((@Entity *)) implements HasNoArgConstructor;
        public HasNoArgConstructor.new() {}
}

The ajc compiler error is:
error at public HasNoArgConstructor.new() {}
       ^^^^^^^^^^^^^^^^^^^^^^^
C:\dev\svnrepos\itsj\linx2\trunk\case\case-model\src\main\aspect\org\piercecountywa\linx\casemanagement\model\aspects\NoArgConstructorMixin.aj:11:0::0
can't define constructors on interfaces

This is what I expect -- constructors don't make sense on interfaces.
Am I doing something wrong in the definition of the aspect?

I've also confirmed that it's not an OpenJPA enhancer error, because
the field initialization code is not placed into the introduced class;
it's in the aspect.  If ajc were to introduce the field **with its
initialization code**, it would work.  If we manually add a no-arg
constructor then decompile the class, we can see ajc's post-construct
after advice that initialized the introduced fields.

Thanks,
Matthew

On Wed, Oct 28, 2009 at 6:18 AM, Simone Gianni <simoneg@...> wrote:

> Hi Matthew,
>
>
> Matthew Adams wrote:
>>
>> =====================
>> // DOES NOT COMPILE
>> public aspect NoArgConstructorMixin {
>>    public ((@Entity *) && !hasmethod(* new())).new() { // can't
>> introduce constructors with this syntax
>>        // how do I ensure fields are initialized in here?  call super()?
>>    }
>> }
>> =====================
>>
>
> you cannot use type patterns when declaring an ITD. The syntax of ITD
> expects a simple type, not a pattern.
>
> So you can write :
>
> public String SomeClass.toString() { ... }
>
> But you cannot write :
>
> public String ((@Entity *)).toString() { ... }
>
> Instead you have to do as you have already done with the Intro interface :
> declare an empty marker interface, then tell AspectJ to inject methods to
> that interface, then use declare parents to place the interface using a type
> pattern.
>
> You should be able to declare also constructors this way.
>
> I'm also using ApsectJ + OpenJPA enhancer, and I'm not facing the problem
> this problem, but probably I don't have fields initialized calling a static
> method. Since OpenJPA enhances the class AFTER ajc (for me too), it should
> see all the fields and methods that ajc has added to the entity classes
> correctly (it surely does for property).
>
> If the OpenJPA introduced constructor does not take into account the fields
> added by AspectJ then maybe you're hitting a bug in the OpenJPA enhancer.
>
> Hope this helps,
> Simone
>
> --
> Simone Gianni            CEO Semeru s.r.l.           Apache Committer
> http://www.simonegianni.it/
>
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@...
> https://dev.eclipse.org/mailman/listinfo/aspectj-users
>



--
mailto:matthew@...
skype:matthewadams12
yahoo:matthewadams
aol:matthewadams12
google-talk:matthewadams12@...
msn:matthew@...
http://matthewadams.me
http://www.linkedin.com/in/matthewadams
_______________________________________________
aspectj-users mailing list
aspectj-users@...
https://dev.eclipse.org/mailman/listinfo/aspectj-users