OSGi Declarative Services & SonarQube - java

I am using OSGi Declarative Services R6. As per the documentation, I created an #interface with function declarations like this:
#ObjectClassDefinition(name = "Hello World OSGi Service")
public #interface Configuration {
#AttributeDefinition(name = "My Foo Property",
description = "A sample string property",
type = AttributeType.STRING)
String my_foo_property() default "bar";
}
My property id gets generated to my.foo.property and the default value will be "bar". However, the problem I am having with SonarQube is that the Sonar Way quality profile doesn't like the my_foo_property function declaration because Method names should comply with a naming convention (squid:S00100) which means it wants something like myFooProperty.
So my question is: With OSGi DS R6, how can I override the generated property id so that my method declaration can be myFooProperty but the key can be my.foo.property.
If that is impossible, how can I add an exception in SonarQube. I don't want to remove this rule, its a good rule.

The names that rule sees as acceptable are the ones that match the regex with which it's configured, which simply makes this a question of crafting the right regex. Probably something like ([a-z][a-zA-Z0-9]*)|([a-z]+\.[a-z]+\.[a-z]+)
However, you mention you're using the Sonar way profile. In later versions of SonarQube, this profile is not editable, so you'll need to create your own profile, set it as default, and copy the rules from Sonar way into it before you can update the regex on this rule.

Related

Kotlin/Java - Non-existent reference in Java annotation on property parameter of constructor compiles

In my company, we're starting to mix Kotlin with Java and found a curious scenario. When I place a Java annotation on a property parameter of a constructor in a Kotlin class, and use a non-existent reference as one of the annotation's parameters, IntelliJ visually indicates an error, but both its build (Ctrl+F9) and maven's build compile normally, without errors.
We're using Java 8 and Kotlin 1.4.20.
Here's the annotation, declared as a Java file:
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.FIELD, ElementType.METHOD})
public #interface Required {
String scope() default "ABC";
}
And here's the Kotlin class using the annotation (class Abc does not exist):
data class Test(
// Compiles normally
#Required(scope = Abc.X)
val text: String
) {
// Compilation error
#Required(scope = Abc.X)
fun x() {
}
}
As mentioned in the code comments, the same annotation placed in a Kotlin function behaves as expected (that is, the code does not compile). An equivalent annotation declared as a Kotlin file also behaves as expected.
When the code is run, the scope variable assumes its default value, so there are no runtime errors.
I've already tried to:
Invalidate IntelliJ cache and restart.
Switch the annotation declaration from #Required(scope = Abc.X) to #field:Required(scope = Abc.X)
I also tried to replicate the behaviour in a brand new project without inheriting from the company's base maven project, but to no avail.
Honestly, I think there's a huge possibility that it is something related to the company's project. I know I haven't specified what my company uses and all the configuration (in fact, the question would get way too big if I did that), but I hope that even with just the basic problem someone may be able to help.
This is a Kotlin compiler bug: argument list is not analyzed for usage of Java annotation with #Target(FIELD) on Kotlin property.
For updates on this please follow the issue https://youtrack.jetbrains.com/issue/KT-33822.

How to get a reference of cucumber RuntimeOptions when using cucumber-java and junit?

I am using cucumber-java in groovy code. I prefer cucumber-java to cucumber-groovy because I can run the tests like plain old good JUnit tests. However, the step definition templates spitted out by cucumber are in java style. Instead, I would like to have a groovy style. For example, in java style, you will get something like
#When("^an HTTP GET request is sent to obtain config.xml of \"([^\"]*)\"$")
public void an_HTTP_GET_request_is_sent_to_obtain_config_xml_of(String arg1) throws Throwable {
// Express the Regexp above with the code you wish you had
throw new PendingException();
}
Since I am using groovy, I would like to get something like
#When(/^an HTTP GET request is sent to obtain config.xml of "([^"]*)"$/)
void 'an HTTP GET request is sent to obtain config.xml of'(String arg1) {
// Express the Regexp above with the code you wish you had
throw new PendingException();
}
I am thinking to implement such a feature. Basically, my idea is to add a new field, maybe called templateLanguage, in cucumber.api.CucumberOptions. When this new field is equal to groovy, then the groovy-style templates will be spitted. This will probably involve an if statement in cucumber.runtime.java.JavaSnippet.template(), such as
if( runtimeOptions.getTemplateLanguage().toLowerCase().equals('groovy') ) {...}
However, my question is: how can I get a reference of the runtimeOptions that is passed in like
#CucumberOptions(
format = ["pretty", "html:build/cucumber"],
features="src/test/resources/cucumber_features/api/job_view.feature",
glue=['com.yahoo.adcd.jenkins.tests.smoke.api.cucumber.job.view'],
strict = true
)
Thank you very much!
In a case like this, you would need to write your own boot class since there is no dependency injection for RuntimeOptions. A good starting location is to look at cucumber.api.cli.Main. You would need to create your own class that extends RuntimeOptions, then add in your logic there.
This solution, however, will not allow you run the app using the CucumberOptions annotation anymore. If you do prefer using the annotation though, you would need to also implement your own custom annotation and override the RuntimeOptionsFactory to use your annotation, and then use that factory in your new main class to create the runtime dynamically.

(ILOG) IBM ODM 8.5 Logging a name of the rule in execution time

I want to create a log such as System.out.println("RuleName : "+ruleName); in IBM ODM rule engine.
So these are what i did;
1- Create BOM virtual methods which are static and get parameter of instance which is
the object of ilog.rules.engine.IlrRuleInstance.
instance ilog.rules.engine.IlrRuleInstance
2- Create BOM to XOM mapping by the following
System.out.println("Log icinde");
String ruleName = "";
if (instance != null )
ruleName = instance.getRuleName();
else
System.out.println("instance null!");
if (ruleName != null) {
System.out.println("RuleName: "+ ruleName);
}
return;
3- Call it in rule flow as an initial or final action.
utility.logla(ruleInstance);
But when i execute the flow my log doesnt work instance is null and ruleName also is null;
How should i configure and set logging feature by using bom. Could you give me an example of it?
Thanks.
So you could use Decision Warehouse that is part of the execution server to trace each execution. This can include which rules have been fired during the execution, but depends on what filters you apply.
Here is the documentation on DW and how to set it up: http://pic.dhe.ibm.com/infocenter/dmanager/v8r5/topic/com.ibm.wodm.dserver.rules.res.managing/topics/con_res_dw_overview.html
It is because you are calling the getRuleName() outside of the context of a rule instance within your rule flow, from what I can see from your description.
If you had a BOM method called from within the action of a rule, you could then call IlrRuleInstance.getRuleName() and it would return the name of the rule (I have done such a thing myself before).
What are you trying to achieve with this logging?
There is a much better way of logging from rules. In your Virtual method, pass the name of the rule itself rather than ruleInstance. You can also verbalize your method and use the same in each rule.
for e.g.:
From BAL:
Log the name of this rule ;
From IRL:
Log(ilog.rules.brl.IlrNameUtil.getBusinessIdentifier(?instance.ruleName));
Another approach is to use the BAL provided above (the name of this rule) within the Rule Flow (Orchestration) for your Rule Application or Module.
Of course this solution should be used only for debugging or troubleshooting scenarios.
Hope this helps.

How do I debug what's wrong when the Endpoints framework stops generating the WEB-INF/*.api-file?

Given a Google Cloud Endpoints project in Eclipse with the servlet-class annotated with #Api(name="helloworld"), the Endpoints framework generates a file named war/WEB-INF/helloworld-v1.api when the project compiles successfully. Sometimes this file is not generated even if there are no compilation errors though - only what I will call "GAE Endpoints code convention errors".
Example - working:
public class TestEntity {
public String Text;
public TestEntity(String text){
Text = text;
}
}
#ApiMethod
public TestEntity getTestEntity(){
return new TestEntity("Hello world");
}
Example - NOT working:
// The TestEntity-class is unchanged
#ApiMethod
public TestEntity getTestEntity(String input){
return new TestEntity("Hello world");
}
The problem with the latter example is that I take a String parameter as input without annotating it with #Named. I know that in this example, but there might be other cases where this is not so obvious.
Is there anywhere where I can read some sort of error log on why the .api file is not generated?
Although I am a fan of code by convention, it really takes the programming efficiency a step back if I cannot get feedback on what I do wrong. Eclipse provides compiler error feedback. The Google Cloud Endpoints Framework should provide Code-By-Convention-Rule-Breaking feedback.
There isn't currently good logging or error messaging when code generation fails, though it's one of the (if not most) requested features. In the interim, here's a list of the common failure cases:
The return type is invalid. Return types must be objects conforming to JavaBean conventions, and types like Object, String, and Integer are not allowed.
One or more argument types are invalid. Methods may accept at most one object in the POST body, and this object should also conform to JavaBean conventions. Methods may accept zero or more arguments via the query string (using the #Named annotation) and these must be scalar types (e.g. String, Integer).
An API, method, or parameter has an invalid name. APIs, methods, and parameters should be named to match the following regular expression: [a-z]+[A-Za-z0-9]*. Convention also suggests using lowerCamelCase for naming (though alllowercase is allowed).

Search OSGI services by properties

How can I distinguish between published OSGI services implementing same interface by their properties?
Assuming that you want to retrieve registered services based on certain values for properties, you need to use a filter (which is based on the LDAP syntax).
For example:
int myport = 5000;
String filter = "&(objectClass=" + MyInterface.class.getName()
+ ")(port=" + myport + ")";
ServiceReference[] serviceReferences = bundleContext.getServiceReferences(null,filter);
where you want to look for services both implementing MyInterface and having a value of the port property equal to myport.
Here is the relevant javadoc for getting the references.
Remark 1:
The above example and javadoc refer to the Release 4.2. If you are not restricted to a J2SE 1.4 runtime, I suggest you to have a look at the Release 4.3 syntax, where you can use generics.
Remark 2: (courtesy of Ray)
You can also pre-check the correctness of your filter by instead creating a Filter object from a filterStr string:
Filter filter = bundleContext.createFilter(filterStr);
which also allows you to match the filter with other criteria. You still pass filterStr to get the references, since there is no overloading that accounts for a Filter argument. Please be aware, however, that in this way you will check the correctness twice: both getServiceReferences and createFilter throw InvalidSyntaxException on parsing the filter. Certainly not a show-stopper inefficiency, I guess, but it is worth mentioning.
Luca's answer above is correct, however it assumes you are using the low level API for accessing services.
If you are using Declarative Services (which I would generally recommend) then the filter can be added to the target attribute of the service reference. For example (using the bnd annotations for DS):
#Reference(target = "(port=8080)")
public void setHttpService(HttpService http) {
// ...
}
In Blueprint you can specify the filter attribute on the reference or reference-list element. For example:
<reference id="sampleRef"
interface="org.sample.MyInterface"
filter="(port=5000)"/>

Categories