QueryDslAccesor Usage

Hi, I’m trying to figure out the better way to use QueryDSL within mi Jira app.

this.queryDslAccessor = ComponentAccessor.getComponent(QueryDslAccessor.class);

return queryDslAccessor.executeQuery(dbConnection -> {

                return dbConnection.newSqlQuery()
                        .select(QIssueLink.ISSUE_LINK.source)
                        .where(QIssueLink.ISSUE_LINK.linktype.eq(subtaskLinkTypeId))
                        .groupBy(QIssueLink.ISSUE_LINK.source)
                        .having(QIssueLink.ISSUE_LINK.source.count().gt(0))
                        .fetch()
                        .stream()
                        .map(issueId -> new QueryLiteral(operand, issueId))
                        .collect(Collectors.toList());
            });

I’ve tried to use QueryDslAccesor class but it thrown an error on the logs each time I try to use it:

2019-11-13 23:32:29,593 http-nio-8080-exec-20 WARN admin 1412x14288x1 49garj 0:0:0:0:0:0:0:1 /secure/QueryComponent!Jql.jspa [c.atlassian.ozymandias.SafePluginPointAccess] A LinkageError indicates that plugin code was compiled with outdated versions. Unable to run plugin code because of 'java.lang.LinkageError - loader constraint violation: loader (instance of org/apache/felix/framework/BundleWiringImpl$BundleClassLoaderJava5) previously initiated loading for a different type with name "com/querydsl/sql/SQLQuery"'.

Also I’ve tried to setup the atlassian-pocketknife-querydsl library but I get lot of OSGI dependencies problems, have someone a working example?

Thanks!

1 Like

Hi! We use atlassian-pocketknife-querydsl successfully in a BitBucket Plugin. We use it only to access or mutate our existing tables, schema creation is still done over ActiveObjects. Pocketknife is worth it, because it encapsulates the oddities of AO.

As for your OSGi problems… it is hard to tell whats causing the problems without logs. I remember that I had to fix some dependency versions due to conflicts. It might have been org.jooq and io.atlassian.fugue. I had to patch some things from pocketknife to get it to work with Bitbucket… but that should not be necessary for Jira.

If you provide logs of the OSGi errors I might be able to help!

Best Regards!

Superb!
I faced two different problems, yesterday.

First I tried to use directly the QueryDslAccessor.class directly available within the jira-core dependency. My applicatio get installed correctly but at runtime the code throws a Exception:

2019-11-13 23:32:29,593 http-nio-8080-exec-20 WARN admin 1412x14288x1 49garj 0:0:0:0:0:0:0:1 /secure/QueryComponent!Jql.jspa [c.atlassian.ozymandias.SafePluginPointAccess] A LinkageError indicates that plugin code was compiled with outdated versions. Unable to run plugin code because of 'java.lang.LinkageError - loader constraint violation: loader (instance of org/apache/felix/framework/BundleWiringImpl$BundleClassLoaderJava5) previously initiated loading for a different type with name "com/querydsl/sql/SQLQuery"'.

When using the following code:

queryDslAccessor.executeQuery(dbConnection -> {

                return dbConnection.newSqlQuery()
                        .select(QIssueLink.ISSUE_LINK.source)
                        .where(QIssueLink.ISSUE_LINK.linktype.eq(subtaskLinkTypeId))
                        .groupBy(QIssueLink.ISSUE_LINK.source)
                        .having(QIssueLink.ISSUE_LINK.source.count().gt(0))
                        .fetch()
                        .stream()
                        .map(issueId -> new QueryLiteral(operand, issueId))
                        .collect(Collectors.toList());
            });

So I decided to use the pockeknife-querydsl library instead. So I did the following:

1.- Add the pockeknife-querydsl as a dependency with compile scope

<dependency>
    <groupId>com.atlassian.pocketknife</groupId>
    <artifactId>atlassian-pocketknife-querydsl</artifactId>
    <version>2.0.1</version>
</dependency>

2.- Exclude some packages from OSGI Bundle

<Import-Package>
    <!-- exclude pocketknife bits we don't need -->
    !net.sf.cglib.proxy,
    !org.jvnet.hudson.annotation_indexer,

    <!-- import (alltheotherthings) -->
    *
</Import-Package>

3.- Enable Spring wiring for pockeknife-querydsl

<build>
    <plugins>
        <plugin>
            <groupId>com.atlassian.plugin</groupId>
            <artifactId>atlassian-spring-scanner-maven-plugin</artifactId>
            <configuration>
                <scannedDependencies>
                    <dependency>
                        <groupId>com.atlassian.pocketknife</groupId>
                        <artifactId>atlassian-pocketknife-querydsl</artifactId>
                    </dependency>
                </scannedDependencies>
            </configuration>
        </plugin>
    </plugins>
</build>

After doing that some dependencies are still missing such as com.atlassian.refapp.api and other packages from joda

I’ll provide you some logs traces with the specific problem, but in the meanwhile could you share with me what other dependencies you have to add with compile scope of what packages did you exclude from net.sf.cglib.proxy and org.jvnet.hudson.annotation_indexer,your osgi bundle to make your app work?

You need to use 5+ version of atlassian-pocketknife-querydsl with jira 8 and later.

1 Like

As said above, you should try it first with e.g. version 5.0.5 … my pom structure wont help you much, as Bitbucket differs quite a bit. I think the only two dependencies I had overriden were:

        <dependency>
            <groupId>io.atlassian.fugue</groupId>
            <artifactId>fugue</artifactId>
            <version>${atlassian.fugue.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.jooq</groupId>
            <artifactId>joor</artifactId>
            <version>${joor.version}</version>
            <scope>compile</scope>
        </dependency>

I did not do other exclusions in the <Import-Package> section, the ones you have should be enough.

As for direct access to QueryDsl… I never tried that… but I suspect again a version conflict… maybe some Jira plugin provides another version of querydsl/pocketknife.

I hope this helps!

Hi,
I’ve setup my application to use atlassian-pocketknife-querydsl v5.0.5 and it get installed correctly without adding any extra depencency within the pom.xml file and only excluding net.sf.cglib.proxy and org.jvnet.hudson.annotation_indexer packages from OSGI Import section.

However, when running the following code:

databaseAccessor.run(databaseConnection -> {

                return databaseConnection.select(QIssueLink.ISSUE_LINK.source)
                        .where(QIssueLink.ISSUE_LINK.linktype.eq(subtaskLinkTypeId))
                        .groupBy(QIssueLink.ISSUE_LINK.source)
                        .having(QIssueLink.ISSUE_LINK.source.count().gt(0))
                        .fetch()
                        .stream()
                        .map(issueId -> new QueryLiteral(operand, issueId))
                        .collect(Collectors.toList());
            }, OnRollback.NOOP);

My application crashed again as you can see in the logs:

2019-11-14 23:12:28,383 http-nio-8080-exec-5 WARN admin 1392x409x3 52himr 127.0.0.1 /rest/issueNav/1/issueTable [c.atlassian.ozymandias.SafePluginPointAccess] A LinkageError indicates that plugin code was compiled with outdated versions. Unable to run plugin code because of 'java.lang.LinkageError - loader constraint violation: when resolving field "source" the class loader (instance of org/apache/felix/framework/BundleWiringImpl$BundleClassLoader) of the referring class, com/atlassian/jira/model/querydsl/QIssueLink, and the class loader (instance of org/apache/catalina/loader/ParallelWebappClassLoader) for the field's resolved type, com/querydsl/core/types/dsl/NumberPath, have different Class objects for that type'.

Note that QIssueLink.class comes from jira-core dependency and is set-up as provided scope.
Any idea?

2 Likes

It’s likely that you have querydsl bundled with your plugin, and Jira has its own querydsl.
So it has the same class name, but they’re technically different classes.

Hi,
I also encountered this problem. Have you solved it?

I ended addind the pocket knife dependency to my own plugin as compile scope, see my pom.xml and note that it should be in that order:

 <!-- See https://bitbucket.org/atlassian/atlassian-pocketknife-querydsl -->
        <dependency>
            <groupId>com.atlassian.pocketknife</groupId>
            <artifactId>atlassian-pocketknife-querydsl</artifactId>
            <version>5.0.5</version>
            <scope>compile</scope>            
        </dependency>     
        
        <!-- Add dependency on jira-core if you want access to JIRA implementation classes as well as the sanctioned API. -->
        <!-- This is not normally recommended, but may be required eg when migrating a plugin originally developed against JIRA 4.x -->   
        <dependency>
            <groupId>com.atlassian.jira</groupId>
            <artifactId>jira-core</artifactId>
            <version>${jira.version}</version>
            <scope>provided</scope>
        </dependency> 

And then I create my own Qxxx objects let’s say QAction, QIssueLink, … and so on because it seems you cannot use the ones provided on Jira directly. Same for xxxDTO clases provided by Jira, i created mines basically pretty similar to those ones as well.

1 Like

Jack, thank you for sharing your experience!
Over last days I repeated the same path as you. First I tried to utilize com.atlassian.jira.database.QueryDslAccessor but whatever I tried I got LinkageError. So finally I came to using pocketknife. In my case I do not need jira-core dependencies as query dsl objects from it cause LinkageError as well.

Has anyone solved this without building everything themselves? :confused:

. I am using 5.0.5 version of PocketKnife.

 <atlassian.pocketknife.querydsl.version>5.0.5</atlassian.pocketknife.querydsl.version>

I get the below error when starting the SDK using atlas-debug when following the example provided in pocketknife repo .

Any clues of what could be the issue ?

org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'databaseAccessorImpl': 
Unsatisfied dependency expressed through constructor parameter 0;

nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'databaseConnectionConverterImpl': 
Unsatisfied dependency expressed through constructor parameter 0;

nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'defaultDialectConfiguration': 
Unsatisfied dependency expressed through constructor parameter 0;

nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'defaultSchemaProvider': 
Unsatisfied dependency expressed through constructor parameter 0;

nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'productSchemaProvider': 
Unsatisfied dependency expressed through constructor parameter 0;

nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
No qualifying bean of type 'com.atlassian.sal.api.rdbms.TransactionalExecutorFactory' available: 
expected single matching bean but found 2: 
salTransactionalExecutorFactory,transactionalExecutorFactory