Skip to content

Commit

Permalink
Merge pull request #13743 from evanchooly/issue12514
Browse files Browse the repository at this point in the history
MongoDB Panache:  Update field access with appropriate get/set methods
  • Loading branch information
evanchooly authored Dec 10, 2020
2 parents 8a17324 + 68759c9 commit 16f5346
Show file tree
Hide file tree
Showing 16 changed files with 242 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.quarkus.hibernate.orm.panache.deployment;

import static io.quarkus.panache.common.deployment.PanacheEntityEnhancer.META_INF_PANACHE_ARCHIVE_MARKER;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
Expand Down Expand Up @@ -63,7 +65,6 @@ public final class PanacheHibernateResourceProcessor {
private static final DotName DOTNAME_ENTITY_MANAGER = DotName.createSimple(EntityManager.class.getName());

private static final DotName DOTNAME_ID = DotName.createSimple(Id.class.getName());
protected static final String META_INF_PANACHE_ARCHIVE_MARKER = "META-INF/panache-archive.marker";

@BuildStep
FeatureBuildItem featureBuildItem() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.quarkus.mongodb.panache.deployment;

import static io.quarkus.deployment.util.JandexUtil.resolveTypeParameters;
import static io.quarkus.panache.common.deployment.PanacheEntityEnhancer.META_INF_PANACHE_ARCHIVE_MARKER;
import static org.jboss.jandex.DotName.createSimple;

import java.util.Collection;
Expand All @@ -27,14 +28,15 @@
import org.jboss.jandex.Type;

import io.quarkus.arc.deployment.ValidationPhaseBuildItem;
import io.quarkus.bootstrap.classloading.ClassPathElement;
import io.quarkus.bootstrap.classloading.QuarkusClassLoader;
import io.quarkus.builder.BuildException;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.ExecutionTime;
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.bean.JavaBeanUtil;
import io.quarkus.deployment.builditem.ApplicationArchivesBuildItem;
import io.quarkus.deployment.builditem.ApplicationIndexBuildItem;
import io.quarkus.deployment.builditem.BytecodeTransformerBuildItem;
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
Expand All @@ -49,8 +51,10 @@
import io.quarkus.mongodb.panache.ProjectionFor;
import io.quarkus.mongodb.panache.jackson.ObjectIdDeserializer;
import io.quarkus.mongodb.panache.jackson.ObjectIdSerializer;
import io.quarkus.panache.common.deployment.MetamodelInfo;
import io.quarkus.panache.common.deployment.PanacheEntityClassesBuildItem;
import io.quarkus.panache.common.deployment.PanacheEntityEnhancer;
import io.quarkus.panache.common.deployment.PanacheFieldAccessEnhancer;
import io.quarkus.panache.common.deployment.PanacheMethodCustomizer;
import io.quarkus.panache.common.deployment.PanacheMethodCustomizerBuildItem;
import io.quarkus.panache.common.deployment.PanacheRepositoryEnhancer;
Expand All @@ -65,7 +69,7 @@ public abstract class BasePanacheMongoResourceProcessor {
public static final DotName PROJECTION_FOR = createSimple(ProjectionFor.class.getName());

@BuildStep
public void buildImperative(CombinedIndexBuildItem index, ApplicationIndexBuildItem applicationIndex,
public void buildImperative(CombinedIndexBuildItem index,
BuildProducer<BytecodeTransformerBuildItem> transformers,
BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
BuildProducer<PropertyMappingClassBuildStep> propertyMappingClass,
Expand Down Expand Up @@ -235,7 +239,8 @@ public void mongoClientNames(ApplicationArchivesBuildItem applicationArchivesBui
}

protected void processEntities(CombinedIndexBuildItem index,
BuildProducer<BytecodeTransformerBuildItem> transformers, BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
BuildProducer<BytecodeTransformerBuildItem> transformers,
BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
BuildProducer<PropertyMappingClassBuildStep> propertyMappingClass,
PanacheEntityEnhancer<?> entityEnhancer, TypeBundle typeBundle) {

Expand Down Expand Up @@ -264,6 +269,39 @@ protected void processEntities(CombinedIndexBuildItem index,
// Register for building the property mapping cache
propertyMappingClass.produce(new PropertyMappingClassBuildStep(modelClass));
}

replaceFieldAccesses(transformers, entityEnhancer, modelClasses);
}

private void replaceFieldAccesses(BuildProducer<BytecodeTransformerBuildItem> transformers,
PanacheEntityEnhancer<?> entityEnhancer, Set<String> modelClasses) {
MetamodelInfo<?> modelInfo = entityEnhancer.getModelInfo();
Set<String> modelClassNamesInternal = new HashSet<>();
for (String entityClassName : modelClasses) {
modelClassNamesInternal.add(entityClassName.replace(".", "/"));
}

if (modelInfo.hasEntities()) {
PanacheFieldAccessEnhancer panacheFieldAccessEnhancer = new PanacheFieldAccessEnhancer(modelInfo);
QuarkusClassLoader tccl = (QuarkusClassLoader) Thread.currentThread().getContextClassLoader();
Set<String> produced = new HashSet<>();

for (ClassPathElement i : tccl.getElementsWithResource(META_INF_PANACHE_ARCHIVE_MARKER)) {
for (String res : i.getProvidedResources()) {
if (res.endsWith(".class")) {
String cn = res.replace("/", ".").substring(0, res.length() - 6);
if (produced.contains(cn)) {
continue;
}
if (!modelClasses.contains(cn)) {
produced.add(cn);
transformers.produce(
new BytecodeTransformerBuildItem(cn, panacheFieldAccessEnhancer, modelClassNamesInternal));
}
}
}
}
}
}

protected void processRepositories(CombinedIndexBuildItem index,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public abstract class PanacheEntityEnhancer<MetamodelType extends MetamodelInfo<
public static final DotName DOTNAME_GENERATE_BRIDGE = DotName.createSimple(GenerateBridge.class.getName());

public static final String JAXB_ANNOTATION_PREFIX = "Ljavax/xml/bind/annotation/";
public static final String META_INF_PANACHE_ARCHIVE_MARKER = "META-INF/panache-archive.marker";
private static final String JAXB_TRANSIENT_BINARY_NAME = "javax/xml/bind/annotation/XmlTransient";
public static final String JAXB_TRANSIENT_SIGNATURE = "L" + JAXB_TRANSIENT_BINARY_NAME + ";";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.quarkus.it.panache;
package io.quarkus.it.panache.resources;

import java.util.List;

Expand All @@ -8,6 +8,9 @@
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

import io.quarkus.it.panache.Book;
import io.quarkus.it.panache.BookDao;

@Path("/book")
public class BookResource {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package io.quarkus.it.mongodb.panache.person
package io.quarkus.it.mongodb.panache.person.resources

import io.quarkus.it.mongodb.panache.person.PersonEntity
import io.quarkus.it.mongodb.panache.person.PersonName
import io.quarkus.it.mongodb.panache.person.Status
import io.quarkus.panache.common.Sort
import java.net.URI
import javax.ws.rs.DELETE
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package io.quarkus.it.mongodb.panache.person
package io.quarkus.it.mongodb.panache.person.resources

import io.quarkus.it.mongodb.panache.person.MockablePersonRepository
import io.quarkus.it.mongodb.panache.person.Person
import io.quarkus.it.mongodb.panache.person.PersonName
import io.quarkus.it.mongodb.panache.person.PersonRepository
import io.quarkus.it.mongodb.panache.person.Status
import io.quarkus.panache.common.Sort
import java.net.URI
import javax.inject.Inject
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
package io.quarkus.it.mongodb.panache.reactive.person
package io.quarkus.it.mongodb.panache.reactive.person.resources


import io.quarkus.it.mongodb.panache.person.PersonName
import io.quarkus.it.mongodb.panache.reactive.person.ReactivePersonEntity
import io.quarkus.panache.common.Sort
import io.smallrye.mutiny.Uni
import java.net.URI
import javax.ws.rs.Consumes
import javax.ws.rs.DELETE
import javax.ws.rs.GET
import javax.ws.rs.PATCH
import javax.ws.rs.POST
import javax.ws.rs.PUT
import javax.ws.rs.Path
import javax.ws.rs.PathParam
import javax.ws.rs.Produces
import javax.ws.rs.QueryParam
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.Response

@Path("/reactive/persons/entity")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
package io.quarkus.it.mongodb.panache.reactive.person
package io.quarkus.it.mongodb.panache.reactive.person.resources


import io.quarkus.it.mongodb.panache.person.Person
import io.quarkus.it.mongodb.panache.person.PersonName
import io.quarkus.it.mongodb.panache.reactive.person.ReactivePersonRepository
import io.quarkus.panache.common.Sort
import io.smallrye.mutiny.Uni
import java.net.URI
import javax.inject.Inject
import javax.ws.rs.Consumes
import javax.ws.rs.DELETE
import javax.ws.rs.GET
import javax.ws.rs.PATCH
import javax.ws.rs.POST
import javax.ws.rs.PUT
import javax.ws.rs.Path
import javax.ws.rs.PathParam
import javax.ws.rs.Produces
import javax.ws.rs.QueryParam
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.Response

@Path("/reactive/persons/repository")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package io.quarkus.it.mongodb.panache;

import org.bson.codecs.pojo.annotations.BsonIgnore;

public class AccessorEntity extends GenericEntity {

public byte b;
public boolean bool;
public char c;
public double d;
public float f;
public int i;
public long l;
public short s;
public String string;
@BsonIgnore
public Object trans;
@BsonIgnore
public Object trans2;

transient int getBCalls = 0;
transient int getTransCalls = 0;
transient int setICalls = 0;
transient int setTransCalls = 0;

public byte getB() {
getBCalls++;
return b;
}

// explicit getter or setter

public Object getTrans() {
getTransCalls++;
return trans;
}

public void setTrans(Object trans) {
setTransCalls++;
this.trans = trans;
}

public void method() {
// touch some fields
@SuppressWarnings("unused")
byte b2 = b;
i = 2;
t = 1;
t2 = 2;
}

public void setI(int i) {
setICalls++;
this.i = i;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package io.quarkus.it.mongodb.panache;

import io.quarkus.mongodb.panache.PanacheMongoEntity;

public abstract class GenericEntity<T> extends PanacheMongoEntity {
public T t;
public T t2;

public T getT2() {
return t2;
}

public void setT2(T t2) {
this.t2 = t2;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package io.quarkus.it.mongodb.panache;

import java.lang.reflect.Method;

import javax.ws.rs.GET;
import javax.ws.rs.Path;

import org.junit.jupiter.api.Assertions;

@Path("/accessors")
public class TestEndpoint {

@GET
public String testAccessors() throws NoSuchMethodException, SecurityException {
checkMethod(AccessorEntity.class, "getString", String.class);
checkMethod(AccessorEntity.class, "isBool", boolean.class);
checkMethod(AccessorEntity.class, "getC", char.class);
checkMethod(AccessorEntity.class, "getS", short.class);
checkMethod(AccessorEntity.class, "getI", int.class);
checkMethod(AccessorEntity.class, "getL", long.class);
checkMethod(AccessorEntity.class, "getF", float.class);
checkMethod(AccessorEntity.class, "getD", double.class);
checkMethod(AccessorEntity.class, "getT", Object.class);
checkMethod(AccessorEntity.class, "getT2", Object.class);

checkMethod(AccessorEntity.class, "setString", void.class, String.class);
checkMethod(AccessorEntity.class, "setBool", void.class, boolean.class);
checkMethod(AccessorEntity.class, "setC", void.class, char.class);
checkMethod(AccessorEntity.class, "setS", void.class, short.class);
checkMethod(AccessorEntity.class, "setI", void.class, int.class);
checkMethod(AccessorEntity.class, "setL", void.class, long.class);
checkMethod(AccessorEntity.class, "setF", void.class, float.class);
checkMethod(AccessorEntity.class, "setD", void.class, double.class);
checkMethod(AccessorEntity.class, "setT", void.class, Object.class);
checkMethod(AccessorEntity.class, "setT2", void.class, Object.class);

try {
checkMethod(AccessorEntity.class, "getTrans2", Object.class);
Assertions.fail("transient field should have no getter: trans2");
} catch (NoSuchMethodException x) {
}

try {
checkMethod(AccessorEntity.class, "setTrans2", void.class, Object.class);
Assertions.fail("transient field should have no setter: trans2");
} catch (NoSuchMethodException x) {
}

// Now check that accessors are called
AccessorEntity entity = new AccessorEntity();
@SuppressWarnings("unused")
byte b = entity.b;
Assertions.assertEquals(1, entity.getBCalls);
entity.i = 2;
Assertions.assertEquals(1, entity.setICalls);
Object trans = entity.trans;
Assertions.assertEquals(0, entity.getTransCalls);
entity.trans = trans;
Assertions.assertEquals(0, entity.setTransCalls);

// accessors inside the entity itself
entity.method();
Assertions.assertEquals(2, entity.getBCalls);
Assertions.assertEquals(2, entity.setICalls);

return "OK";
}

private void checkMethod(Class<?> klass, String name, Class<?> returnType, Class<?>... params)
throws NoSuchMethodException, SecurityException {
Method method = klass.getMethod(name, params);
Assertions.assertEquals(returnType, method.getReturnType());
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.quarkus.it.mongodb.panache.person;
package io.quarkus.it.mongodb.panache.person.resources;

import java.net.URI;
import java.util.HashSet;
Expand All @@ -8,6 +8,9 @@
import javax.ws.rs.*;
import javax.ws.rs.core.Response;

import io.quarkus.it.mongodb.panache.person.PersonEntity;
import io.quarkus.it.mongodb.panache.person.PersonName;
import io.quarkus.it.mongodb.panache.person.Status;
import io.quarkus.panache.common.Sort;

@Path("/persons/entity")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.quarkus.it.mongodb.panache.person;
package io.quarkus.it.mongodb.panache.person.resources;

import java.net.URI;
import java.util.HashSet;
Expand All @@ -9,6 +9,11 @@
import javax.ws.rs.*;
import javax.ws.rs.core.Response;

import io.quarkus.it.mongodb.panache.person.MockablePersonRepository;
import io.quarkus.it.mongodb.panache.person.Person;
import io.quarkus.it.mongodb.panache.person.PersonName;
import io.quarkus.it.mongodb.panache.person.PersonRepository;
import io.quarkus.it.mongodb.panache.person.Status;
import io.quarkus.panache.common.Sort;

@Path("/persons/repository")
Expand Down
Loading

0 comments on commit 16f5346

Please sign in to comment.