HHH-12786 Allow to call methods when the interceptor is not set yet

Typically, if the constructor calls instrumented methods, the
interceptor is not defined yet and we get a NPE.
This commit is contained in:
Guillaume Smet 2018-07-12 18:43:19 +02:00
parent 297031319d
commit 0fda6be86e
5 changed files with 180 additions and 1 deletions

View File

@ -26,6 +26,7 @@ public class BasicProxyFactoryImpl implements BasicProxyFactory {
private final Class proxyClass;
@SuppressWarnings("unchecked")
public BasicProxyFactoryImpl(Class superClass, Class[] interfaces, ByteBuddyState bytebuddy) {
if ( superClass == null && ( interfaces == null || interfaces.length < 1 ) ) {
throw new AssertionFailure( "attempting to build proxy without any superclass or interfaces" );
@ -39,7 +40,7 @@ public class BasicProxyFactoryImpl implements BasicProxyFactory {
.implement( interfaces == null ? NO_INTERFACES : interfaces )
.defineField( ProxyConfiguration.INTERCEPTOR_FIELD_NAME, ProxyConfiguration.Interceptor.class, Visibility.PRIVATE )
.method( ElementMatchers.isVirtual().and( ElementMatchers.not( ElementMatchers.isFinalizer() ) ) )
.intercept( MethodDelegation.toField( ProxyConfiguration.INTERCEPTOR_FIELD_NAME ) )
.intercept( MethodDelegation.to( ProxyConfiguration.InterceptorDispatcher.class ) )
.implement( ProxyConfiguration.class )
.intercept( FieldAccessor.ofField( ProxyConfiguration.INTERCEPTOR_FIELD_NAME ).withAssigner( Assigner.DEFAULT, Assigner.Typing.DYNAMIC ) )
.make()

View File

@ -0,0 +1,21 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.component.proxy;
import javax.persistence.Entity;
@Entity
public class Adult extends Person {
public Adult() {
someInitMethod();
}
@Override
public void someInitMethod() {
}
}

View File

@ -0,0 +1,47 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.component.proxy;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import java.util.List;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.TestForIssue;
import org.junit.Test;
/**
* @author Guillaume Smet
* @author Oliver Libutzki
*/
public class ComponentBasicProxyTest extends BaseEntityManagerFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[]{
Person.class, Adult.class
};
}
@Test
@TestForIssue(jiraKey = "HHH-12786")
public void testBasicProxyingWithProtectedMethodCalledInConstructor() {
doInJPA( this::entityManagerFactory, entityManager -> {
Adult adult = new Adult();
adult.setName( "Arjun Kumar" );
entityManager.persist( adult );
} );
doInJPA( this::entityManagerFactory, entityManager -> {
List<Adult> adultsCalledArjun = entityManager
.createQuery( "SELECT a from Adult a WHERE a.name = :name", Adult.class )
.setParameter( "name", "Arjun Kumar" ).getResultList();
Adult adult = adultsCalledArjun.iterator().next();
entityManager.remove( adult );
} );
}
}

View File

@ -0,0 +1,68 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.component.proxy;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.Table;
@Entity
@Table(name = "person")
@IdClass(PersonId.class)
public abstract class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private int id;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "clientId")
private int clientId;
@Column(name = "name")
private String name;
@Column(name = "title")
private String title;
public Person() {
someInitMethod();
}
public void someInitMethod() {
}
public int getId() {
return id;
}
public int getClientId() {
return clientId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTitle(String name) {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}

View File

@ -0,0 +1,42 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.component.proxy;
import java.io.Serializable;
@SuppressWarnings("all")
public class PersonId implements Serializable {
private int id;
private int clientId;
public PersonId() {
}
public PersonId(int aId, int aClientId) {
setId( aId );
setClientId( aClientId );
}
public int getId() {
return id;
}
public void setId(int aId) {
this.id = aId;
}
public int getClientId() {
return clientId;
}
public void setClientId(int aClientId) {
clientId = aClientId;
}
}