querydsl-collections

348 views
Skip to first unread message

timowest

unread,
Sep 27, 2011, 2:36:43 AM9/27/11
to quer...@googlegroups.com
Hello I am receiving this error and I am unsure why. I am just performing a query on a collection of a simple type using an alias. I hope someone can help me!

I am using open-jdk-1.6

Exception in thread "main" java.lang.NoClassDefFoundError: net/sf/cglib/proxy/Callback
at com.mysema.query.alias.Alias.<clinit>(Alias.java:44)
at TestingMain.main(TestingMain.java:23)
Caused by: java.lang.ClassNotFoundException: net.sf.cglib.proxy.Callback
at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
at java.lang.ClassLoader.loadClass(ClassLoader.java:323)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
at java.lang.ClassLoader.loadClass(ClassLoader.java:268)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:336)
... 2 more


Here is a sample of the code


       
ArrayList<TestClass> testSource = new ArrayList<TestClass>();

        testSource
.add(new TestClass("old timer", 89));
        testSource
.add(new TestClass("bob", 22));
        testSource
.add(new TestClass("joe", 24));

       
TestClass test = alias(TestClass.class, "TestClass");
       
List<TestClass> tests = from($(test),testSource)
                                 
.where($(test.getAge()).in(24))
                                 
.list($(test));

       
for (TestClass t : tests)
       
{
               
System.out.println(t.getName());
       
}



Thank you so much!

timowest

The cglib dependency comes from querydsl-core :


   
<dependency>
     
<groupId>cglib</groupId>
     
<artifactId>cglib</artifactId>
     
<version>2.2</version>
   
</dependency>


Make sure CGLIB is visible from your project. I haven't tested querydsl-collections with OpenJDK, but it should definitely work.

Is net.sf.cglib.proxy.Enhancer visible?

If you use Eclipse, make sure cglib 2.2 is visible as an dependency in your project.

The path to the dependency is

querydsl-collection > querydsl-core > cglib


If switching to a Sun JDK is an option, then this could be tried too.

halasear

Where would this dependency be located? I am rather new to how Maven works (I come from a .Net development background). Would I have to find it within the repository for which Maven saves the dependencies to? (in the $USER/.m2/repository/ directory (in a unix-like environment))?

Is there a reason why Maven does not create a jar that compiles all of the dependencies into one instead of having to find and locate all of the dependencies individually? I think that is what is the most frustrating aspect of getting this very useful library to work.

The OpenJDK is the open sourced SunJDK (same code base), so I would think it should not make a difference. It's not like it's the GNU JDK (different code base).

Thanks again for all of the help!

Additionally, I am using Eclipse

timowest

Where would this dependency be located? I am rather new to how Maven works (I come from a .Net development background). Would I have to find it within the repository for which Maven saves the dependencies to? (in the $USER/.m2/repository/ directory (in a unix-like environment))?


Yes, it is fetched into your local repository from a remote one (e.g. http://repo1.maven.org).

Is there a reason why Maven does not create a jar that compiles all of the dependencies into one instead of having to find and locate all of the dependencies individually?


The pom.xml declares the dependencies and Maven fetches them. So not really much to manage manually.

I think that is what is the most frustrating aspect of getting this very useful library to work.


If you don't use Maven to do your builds you can request an alternative way to package Querydsl.

We could for example provide zip or tgz files with all the dependencies of the hql, sql, jdoql and collections modules.


We at Mysema and probably also most of the Querydsl users use Maven, so until there was no need for an alternative packaging.

If you want to keep on using Maven then you could for example run the following Maven command in your project to get a proper eclipse setup for it


mvn
-DdownloadSources eclipse:clean eclipse:eclipse


This will set you up with an Eclipse project with proper Maven dependencies.

If you use IDEA then the following goal will do the job


mvn idea
:clean idea:idea


But if you want to use Querydsl without Maven, just tell me, and we will provide releases with all needed jars packaged in zips and/or tgz files.

Here are some Maven IDE integration links :

IDEA :
http://maven.apache.org/plugins/maven-idea-plugin/usage.html

Eclipse :
http://maven.apache.org/plugins/maven-eclipse-plugin/
http://maven.apache.org/eclipse-plugin.html

halasear

Ohh I get it now! I didn't realize that there were separate projects created for each package. I had run the command from another thread that you had commented in (a little different from the one from the documentation).

Thank you so much, this makes so much more sense! It will not be necessary for you to create a combined jar, not after I have figured out how to get all of the projects to work with their dependencies. I had actually already installed the maven plugin for eclipse, I just didn't quite understand how it worked.

So again, unfortunately, when I run the same blip of code I still get an error, though it's a different one. I am currently running 1.1.7, would that make a difference? I noticed that 1.2.0 has been released.

Exception in thread "main" java.lang.RuntimeException
at com.mysema.query.util.FactoryMap.get(FactoryMap.java:50)
at com.mysema.query.alias.AliasFactory.createAliasForVariable(AliasFactory.java:55)
at com.mysema.query.alias.Alias.alias(Alias.java:155)
at TestingMain.main(TestingMain.java:23)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at com.mysema.query.util.FactoryMap.get(FactoryMap.java:46)
... 3 more
Caused by: java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
at net.sf.cglib.proxy.Enhancer.emitConstructors(Enhancer.java:721)
at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:499)
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)
at com.mysema.query.alias.AliasFactory.createProxy(AliasFactory.java:73)
at com.mysema.query.alias.AliasFactory.access$0(AliasFactory.java:60)
at com.mysema.query.alias.AliasFactory$2.create(AliasFactory.java:38)
... 8 more


Once again, thank you so much I greatly appreciate all of the help that you have given me!

And I would like to add that cglib is included!

timowest

Caused by: java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given


This happens if you try to create an alias instance for a class without a public empty constructor. Cglib subclasses the given type dynamically and it needs a public empty constructor to instantiate them.

So make sure that the classes you use for Alias-usage have an empty constructor.

halasear

Well, you make it sound so easy!

I didn't think it was pertaining to my class. Again, thank you so much!

timowest

> Well, you make it sound so easy!

;) I have used Hibernate quite a lot, which has similar restrictions.

I willl mention this restriction in the documentation.

halasear

Okay, now I am trying to reproduce the use of the PEntity. However, it is complaining about invalid type (which makes sense) for testClass static variable. However the documentation of 3.1.1 "Best Practices" essentially performs the following.


import com.mysema.query.types.path.*;

public class QTestClass extends PEntity<TestClass> {
       
public static final TestClass testClass = new QTestClass("testClass");
       
       
public QTestClass(String variable) {
               
super(TestClass.class, PathMetadataFactory.forVariable(variable));
       
}
}


then from looking at the example of the documentation for 2.3 querying collections it discusses the following in 2.3.2. Which I am trying to replicate as follows. This too does not as the documentation lists (which once again makes sense because the String class does not contain the following functions.)


               
TestClass test2 = QTestClass.testClass;
               
for (TestClass t : select(testSource, test2.getName().in("bob"))){
                   
System.out.println(t.getName());  
               
}



Thanks again, I really appreciate all of the help.

Is there a test project that contains examples?

timowest

Here is a working example for your case :


public class SimpleTest {

   
public static class TestClass {

       
private int age;
       
       
private String name;

       
public TestClass(String name, int age){
           
this.name = name;
           
this.age = age;
       
}
       
       
public TestClass(){}
       
       
public String getName() {
           
return name;
       
}

       
public void setName(String name) {
           
this.name = name;
       
}

       
public int getAge() {
           
return age;
       
}

       
public void setAge(int age) {
           
this.age = age;
       
}
       
   
}

   
public static class QTestClass extends PEntity<TestClass> {

       
public static final QTestClass testClass = new QTestClass("testClass");

       
public final PString name = createString("name");
       
       
public final PNumber<Integer> age = createNumber("age",Integer.class);
       
       
public QTestClass(String variable) {
           
super(TestClass.class, PathMetadataFactory.forVariable(variable));
       
}

   
}
   
   
@Test
   
public void test(){
       
List<TestClass> testSource = new ArrayList<TestClass>();
        testSource
.add(new TestClass("old timer", 89));
        testSource
.add(new TestClass("bob", 22));
        testSource
.add(new TestClass("joe", 24));
       
       
QTestClass tc = QTestClass.testClass;
       
for (TestClass t : MiniApi.from(tc, testSource).where(tc.name.eq("bob")).list(tc)){
           
System.out.println(t.getName());  
       
}
       
       
for (TestClass t : MiniApi.from(tc, testSource).where(tc.name.in("bob")).list(tc)){
           
System.out.println(t.getName());  
       
}
   
}

}


There is an error in the reference's Best Practices section. The correct form for default variables is


QAccount extends PEntity<Account>{
     
   
public static final Account account = new QAccount("account");
}


If you want to automatically create Querydsl query types (PEntity subclasses) for your domain types, you can annotate them with the QueryEntity annotation and adding the following plugin configuration into your project's Maven configuration (pom.xml) :


   
<plugin>
     
<groupId>com.mysema.maven</groupId>
     
<artifactId>maven-apt-plugin</artifactId>
     
<version>0.3.0</version>
     
<executions>
       
<execution>
         
<goals>
           
<goal>process</goal>
         
</goals>
         
<configuration>
           
<outputDirectory>target/generated-sources/java</outputDirectory>
           
<processor>com.mysema.query.apt.QuerydslAnnotationProcessor</processor>
         
</configuration>
       
</execution>
     
</executions>
   
</plugin>


This will also be properly document in the next release's reference documentation.

For more examples see the unit tests for querydsl-collections. They are in the src/test/java folder.

Sorry, the form for default variables is of course :


QAccount extends PEntity<Account>{
     
   
public static final QAccount account = new QAccount("account");
}

halasear

Sweet! Thanks a million!

I will test these later tonight!

Cyberax

A 'small' request - maybe you can add a cache of compiled expressions? I've accidentally used qdsl-collections in an internal loop and it HURTs.

timowest

Ok, will do that and let you know when it's finished.

Alex (aka Cyberax), can you give my an example that is really slow with the current implementation?

There is an compilation overhead for first-time queries, but subsequent iterations are faster.

Without real examples it is difficult to promise any improvement, I don't want to optimize wrong aspects ;)


Reply all
Reply to author
Forward
0 new messages