【问题标题】:Using Sonar's web service java client to persist properties使用 Sonar 的 web 服务 java 客户端来持久化属性
【发布时间】:2024-01-06 03:01:01
【问题描述】:

如何持久化 Sonar 属性using Sonar's web service java client

[编辑:我现在意识到 Web 服务客户端不适用于开发插件;而应该使用 Sonar 的 API 中的其他类。请参阅我接受的答案。]

我打算为声纳制作一个插件。与此同时,我正在熟悉 Sonar 的 API,尤其是 Sonar 的 Web 服务 Java 客户端。我试图弄清楚如何保留声纳属性。我写了以下代码:

    package testers;

    import org.sonar.wsclient.Sonar;
    import org.sonar.wsclient.services.Property;
    import org.sonar.wsclient.services.PropertyCreateQuery;
    import org.sonar.wsclient.services.PropertyQuery;

    public class PropertyPersister {

        public static Sonar localSonar;
        public static Property sonarStartTime;
        public static PropertyQuery findStartTime;
        public static Property testProperty;
        public static PropertyQuery findTestProperty;
        public static String testKey = "testKey";
        public static String testValue = "testValue";


        /**
         * @param args
         */
        public static void main(String[] args) {

            //localSonar = Sonar.create("http://localhost:9000");//pointed to my instance of Sonar

            //EDIT: using this line instead, but it still gives the same stack trace.
                    localSonar = Sonar.create("http://localhost:9000", "admin", "admin");//pointed to my instance of Sonar

            findStartTime = PropertyQuery.createForKey("sonar.core.startTime");//creating query for a key I know exists
            sonarStartTime = localSonar.find(findStartTime);//retrieve property object from my Sonar's database
            System.out.println(sonarStartTime);//print out this object

            PropertyCreateQuery testCreateQuery = new PropertyCreateQuery(testKey, testValue);//Query to create test property


            localSonar.create(testCreateQuery);//With this line, I'm trying to persist my test property

            findTestProperty = PropertyQuery.createForKey(testKey);//creating query for retrieving test property
            testProperty = localSonar.find(findTestProperty);//line 36: retrieve property object from my Sonar's database
            System.out.println(testProperty);//print test property
        }
    }

此代码打印出已经存在的 sonarStartTime 属性:

[sonar.core.startTime:2013-03-14T08:05:42-0700]

然后是倒数第二行抛出的空指针异常。异常消息包括:

 org.sonar.wsclient.unmarshallers.UnmarshalException: Can not parse the response of query /api/properties/testKey?: {"err_code":404,"err_msg":"Property not found: testKey"}

使用 MySQL 工作台,我确认确实,我的测试属性从未持久化。显然,我正在以错误的方式解决这个问题。所以,重申我的问题,我怎样才能在 Sonar using Sonar's web service java client 中保留一个属性?

[编辑] 这是带有堆栈跟踪的完整控制台输出:

[sonar.core.startTime:2013-03-14T08:05:42-0700]
Exception in thread "main" org.sonar.wsclient.unmarshallers.UnmarshalException: Can not parse the response of query /api/properties/testKey?: {"err_code":404,"err_msg":"Property not found: testKey"}

    at org.sonar.wsclient.Sonar.find(Sonar.java:56)
    at testers.PropertyPersister.main(PropertyPersister.java:36)
Caused by: java.lang.ClassCastException: org.json.simple.JSONObject cannot be cast to java.util.ArrayList
    at org.sonar.wsclient.JdkUtils.getArraySize(JdkUtils.java:87)
    at org.sonar.wsclient.unmarshallers.AbstractUnmarshaller.toModel(AbstractUnmarshaller.java:34)
    at org.sonar.wsclient.Sonar.find(Sonar.java:54)
    ... 1 more

【问题讨论】:

  • 我想得越多,我就越认为我确实在以正确的方式做这件事,但是在某个地方有某种晦涩难懂的设置,不会让我坚持任何事情。我一直无法找到这个设置可能是什么......如果有人能指出我正确的方式,我将不胜感激。
  • 我现在意识到 Web Service Client 不适用于开发插件,而是适用于单独的应用程序,因此应该使用 Sonar 的 API 中的其他类。查看我接受的答案。

标签: java api plugins sonarqube


【解决方案1】:

Sonar 简要说明了如何重用其 API here 的现有组件。

您可以简单地在您尝试持久化属性的类的构造函数中声明一个 DatabaseSession。例如:

import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.configuration.Property;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;

public class PropertyPersister{

    private DatabaseSession session;
    private Project project;
    private Property newProperty;

    public PropertyPersister (DatabaseSession session, Project project){
    this.session = session;
    this.project = project; 
    }

    private void persistProperty (Resource resource) {
        int resourceId= resource.getId();       
        newProperty = new Property("sonar.myFabulousProperty", "someValue", resourceId);
        session.save(newProperty);      
    }
}

【讨论】:

  • Sonar 的 Web 服务客户端 API 并不真正适用于实际插件。毕竟这是我真正想要的。谢谢。
【解决方案2】:

如果您希望能够将数据推送到 Sonar,则需要拥有管理员凭据。

所以你应该像这样创建“org.sonar.wsclient.Sonar”实例:

localSonar = Sonar.create("http://localhost:9000", "admin", "admin");

【讨论】:

  • 嗨,Fabrice,感谢您的回复!但是,我尝试按照您的建议添加管理员凭据,但它仍然不起作用并且给了我相同的堆栈跟踪,所以我认为还有一些我对 api 的理解不正确的地方。将 CreatePropertyQuery 传递给 localSonar.create() 是保持属性的正确方法吗?
  • 更正上述评论。当我的意思是“PropertyCreateQuery”时,我在上面的评论中说“CreatePropertyQuery”。所以我的问题是,如果我想使用 wsclient 保留属性,是否将 PropertyCreateQuery 传递给方法 localSonar.create() 是正确的方法吗?如果是这样,我做错了什么导致我的测试属性无法持续存在?