Skip to content

Instantly share code, notes, and snippets.

@Alex-Ikanow
Last active December 16, 2015 15:28
Show Gist options
  • Save Alex-Ikanow/5455727 to your computer and use it in GitHub Desktop.
Save Alex-Ikanow/5455727 to your computer and use it in GitHub Desktop.
Sample code showing how to persist a dynamically created (actually modified) class to MongoDB using Kundera (updated to demonstrate JPQL queries, which requires slight hack for classes not discovered by persistence.xml)
// 1] persistence.xml, this can be anywhere in the classpath
//<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="2.0">
//<persistence-unit name="mongoPU">
// <provider>com.impetus.kundera.KunderaPersistence</provider>
// <class>com.ikanow.infinit.e.harvest.test.NoSqlHarvestTest$TemplateClass</class>
// <properties>
// <property name="kundera.client.lookup.class" value="com.impetus.client.mongodb.MongoDBClientFactory"/>
// <property name="kundera.port" value="27017" />
// <property name="kundera.dialect" value="mongodb" />
// <property name="kundera.cache.provider.class" value="com.impetus.kundera.cache.ehcache.EhCacheProvider" />
// <property name="kundera.cache.config.resource" value="/ehcache-test.xml" />
// <!-- The following will get overridden -->
// <property name="kundera.nodes" value="localhost" />
// <property name="kundera.keyspace" value="test" />
// </properties>
//</persistence-unit>
//</persistence>
// 2] Code
package com.ikanow.infinit.e.harvest.test;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Id;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.Table;
import com.impetus.kundera.metadata.model.KunderaMetadata;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtNewConstructor;
import javassist.NotFoundException;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ClassFile;
import javassist.bytecode.ConstPool;
import javassist.bytecode.annotation.Annotation;
import javassist.bytecode.annotation.StringMemberValue;
public class NoSqlHarvestTest {
// Use this to initialize
@Entity
public static class TemplateClass {
// Attributes, annotations, and getters/setters
}
@Entity
@Table(name = "TEST_CLASS", schema = "KunderaTest@mongoPU")
public static class KunderaControlTest {
@Id
private String idField;
@Column(name="TEST_FIELD")
private String testField;
// Functions, no annotations needed
public KunderaControlTest() {}
public void setTestField(String testField) {
this.testField = testField;
}
public String getTestField() {
return testField;
}
public void setIdField(String idField) {
this.idField = idField;
}
public String getIdField() {
return idField;
}
}
/**
* @param args
* @throws CannotCompileException
* @throws NotFoundException
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void main(String[] args) throws CannotCompileException, NotFoundException, ClassNotFoundException, InstantiationException, IllegalAccessException {
// 1] Class creation (http://stackoverflow.com/questions/3028304/javassist-annoations-problem?rq=1)
// 1.1] Create a class
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("com.ikanow.infinit.e.harvest.test.NoSqlHarvestTest$TemplateClass");
CtField testField = new CtField(pool.get("java.lang.String"), "testField", cc);
cc.addField(testField);
CtField idField = new CtField(pool.get("java.lang.String"), "idField", cc);
cc.addField(idField);
// 1.2] Annotations
ClassFile ccFile = cc.getClassFile();
ConstPool constpool = ccFile.getConstPool();
// 1.2.1] Create an annotation for the class
AnnotationsAttribute attrClass = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag);
// 1.2.1.1] Entity
Annotation annotEntity = new Annotation("javax.persistence.Entity", constpool);
attrClass.addAnnotation(annotEntity);
// 1.2.1.2] Table info
Annotation annotTable = new Annotation("javax.persistence.Table", constpool);
annotTable.addMemberValue("name", new StringMemberValue("TEST_CLASS", ccFile.getConstPool()));
annotTable.addMemberValue("schema", new StringMemberValue("KunderaTest@mongoPU", ccFile.getConstPool()));
attrClass.addAnnotation(annotTable);
// 1.2.1.3] Attach the annotation to the class
ccFile.addAttribute(attrClass);
// 1.2.2] Create an annotation for the field
// 1.2.2.1] Annotation Id
AnnotationsAttribute attrIdField = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag);
Annotation annotId = new Annotation("javax.persistence.Id", constpool);
attrIdField.addAnnotation(annotId);
// 1.2.2.2] Annotation Column (name="testField")
AnnotationsAttribute attrTestField = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag);
Annotation annotCol = new Annotation("javax.persistence.Column", constpool);
annotCol.addMemberValue("name", new StringMemberValue("TEST_FIELD", ccFile.getConstPool()));
attrTestField.addAnnotation(annotCol);
// 1.2.2.3] Attach the annotation to the field
idField.getFieldInfo().addAttribute(attrIdField);
testField.getFieldInfo().addAttribute(attrTestField);
// 1.3] Add methods
// example just to set a field
if (cc.getConstructors().length > 0) {
cc.removeConstructor(cc.getConstructors()[0]);
}
CtConstructor ccCon = CtNewConstructor.make("public TemplateClass() { idField = \"alex_id\"; testField = \"alex\"; }", cc);
cc.addConstructor(ccCon);
// 1.4] Interlude: print the class/annotation out to check it looks sensible
System.out.println("Class Info: " + cc.toString());
for (Object annotObj: cc.getAnnotations()) {
System.out.println("Class Annotation: " + annotObj.toString());
}
for (Object annotObj: testField.getAnnotations()) {
System.out.println("Field Annotation: " + annotObj.toString());
}
// 1.5] Create an instance
// 1.5.1] (main test)
Object instanceOfMyClass = cc.toClass().newInstance();
// 1.5.2] (control test)
KunderaControlTest controlInstance = new KunderaControlTest();
controlInstance.setIdField("control_id");
controlInstance.setTestField("control_instance");
// 2] Integrate into Kundera (http://anismiles.wordpress.com/2010/07/14/kundera-now-jpa-1-0-compatible/)
// 2.1] Create a persistence hash map (http://xamry.wordpress.com/2011/05/02/working-with-mongodb-using-kundera/)
Map kunderaMongoConfig = new HashMap();
kunderaMongoConfig.put("kundera.nodes", "localhost");
kunderaMongoConfig.put("kundera.keyspace", "KunderaTest");
// 2.2] Instantiate Kundera
EntityManagerFactory factory = Persistence.createEntityManagerFactory("mongoPU", kunderaMongoConfig);
EntityManager manager = factory.createEntityManager();
// 2.3] Save an object
System.out.println("Persisting control instance..." + controlInstance.getClass().toString());
manager.persist(controlInstance);
System.out.println("Persisting dynamically created instance..." + instanceOfMyClass.getClass().toString());
manager.persist(instanceOfMyClass);
System.out.println("Everything persisted!");
// 2.4] Use JPQL/JPA (also test output as JSON)
// Find by Id
KunderaControlTest x = manager.find(KunderaControlTest.class, "control_id");
System.out.println("CONTROL RESULT findOne: " + new com.google.gson.Gson().toJson(x));
TemplateClass y = manager.find(TemplateClass.class, "control_id");
System.out.println("DYNAMIC RESULT findOne: " + new com.google.gson.Gson().toJson(y));
// Presumably because persistence.xml isn't at the top of the class path, need this hack to make it work
Map<String, List<String>> clazzHack = new HashMap<String, List<String>>();
clazzHack.put("TemplateClass", Arrays.asList("mongoPU"));
KunderaMetadata.INSTANCE.getApplicationMetadata().setClazzToPuMap(clazzHack);
String query = "Select p from TemplateClass p where p.testField = control_instance";
//String query = "Select p from TemplateClass p";
Query q = manager.createQuery(query);
List results = q.getResultList();
if (null != results) {
System.out.println("Executed query '" +query + "': " + results.size());
for (Object obj: results) {
System.out.println("RESULT: " + new com.google.gson.Gson().toJson(obj));
}
}
else {
System.out.println("No results for query: " + query);
}
// 2.5] Check that the I can create different dynamic classes from the same template class
//TODO
manager.close();
factory.close();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment