quarkus native reflection configuration for whole package - kotlin

I'm building quarkus native and using Stripe sdk as external library.
In order to support Stripe sdk it I needed to create reflection-config.json file and set in the application.properties quarkus.native.additional-build-args=-H:ReflectionConfigurationFiles=reflection-config.json
The reflection-config.json looks like so:
{
"name": "com.stripe.model.Customer",
"allDeclaredConstructors": true,
"allPublicConstructors": true,
"allDeclaredMethods": true,
"allPublicMethods": true,
"allDeclaredFields": true,
"allPublicFields": true
},
{
"name": "com.stripe.model.Customer$InvoiceSettings",
"allDeclaredConstructors": true,
"allPublicConstructors": true,
"allDeclaredMethods": true,
"allPublicMethods": true,
"allDeclaredFields": true,
"allPublicFields": true
},
{
"name": "com.stripe.model.StripeError",
"allDeclaredConstructors": true,
"allPublicConstructors": true,
"allDeclaredMethods": true,
"allPublicMethods": true,
"allDeclaredFields": true,
"allPublicFields": true
},
{
"name": "com.stripe.model.PaymentIntent",
"allDeclaredConstructors": true,
"allPublicConstructors": true,
"allDeclaredMethods": true,
"allPublicMethods": true,
"allDeclaredFields": true,
"allPublicFields": true
},
{
"name": "com.stripe.model.PaymentMethod",
"allDeclaredConstructors": true,
"allPublicConstructors": true,
"allDeclaredMethods": true,
"allPublicMethods": true,
"allDeclaredFields": true,
"allPublicFields": true
}....
and so on.
It contains too many classes.
My question is if there is a way to set the whole package instead of tons of classes?
For example:
{
"name": "com.stripe.model.*",
"allDeclaredConstructors": true,
"allPublicConstructors": true,
"allDeclaredMethods": true,
"allPublicMethods": true,
"allDeclaredFields": true,
"allPublicFields": true
}
Didn't find any mention for it.

See update below.
I'm having the exact same use case to programmatically add all classes of a package for reflection without writing an extension.
My goal is to add jOOQ generated DB classes for reflection so I can use them in a native compiled Quarkus GraalVM image with RESTEasy Reactive Jackson.
As there are a lot of these classes I don't really want to manually populate the reflection-config.json or the targets with a #RegisterForReflection annotation on a empty class.
I'm using Quarkus 2.7.0.Final (not io.quarkus.platform as it is not released yet) with Gradle 7.3.3 and tried the following, which unfortunately does not work.
But I guess this only works when building extensions 🤔
package com.example.restapi.graal;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.IndexView;
public class JooqReflectionProcessor {
private static final String JOOQ_DB_REFLECT_CLASSES = "com\\.example\\.restapi\\.db\\..+\\.tables\\.(pojos|records)\\..+";
#BuildStep
public void build(BuildProducer<ReflectiveClassBuildItem> reflectiveClass, CombinedIndexBuildItem indexBuildItem) {
IndexView index = indexBuildItem.getIndex();
for (ClassInfo clazz : index.getKnownClasses()) {
if (clazz.name().toString().matches(JOOQ_DB_REFLECT_CLASSES)) {
reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, clazz.name().toString()));
}
}
}
}
Update:
It ain't pretty but I ended up writing a Gradle task which automatically creates the desired jOOQ reflection class with the #RegisterForReflection(targets = {...}) annotation:
task writeJooqReflectionClass {
DefaultSourceDirectorySet sourceSet = project.sourceSets.findByName('main').java
File jooqSrcDir = sourceSet.srcDirs
.stream()
.filter { it.path.replace('\\', '/').matches('.+src/generated/jooq/main') }
.findFirst()
.get()
ArrayList<String> classesForReflection = sourceSet
.filter {
it.path.contains(jooqSrcDir.path) &&
it.path.replace('\\', '/').matches('.+tables/(pojos|records)/.+') &&
it.path.endsWith('.java')
}
.collect { it.path.replaceAll('[\\\\|/]', '.').substring(jooqSrcDir.path.length() + 1).replace('.java', '.class') }
Collections.sort(classesForReflection)
File file = new File("${jooqSrcDir.path}/com/example/restapi/db", "JooqReflectionConfig.java")
file.getParentFile().mkdirs()
file.text = """\
package com.example.restapi.db;
import io.quarkus.runtime.annotations.RegisterForReflection;
#RegisterForReflection(targets = {
${String.join(',\n ', classesForReflection)}
})
public class JooqReflectionConfig {
}
""".stripIndent()
}
compileJava.dependsOn(writeJooqReflectionClass)
For example produces Class com.example.restapi.db.JooqReflectionConfig with content:
package com.example.restapi.db;
import io.quarkus.runtime.annotations.RegisterForReflection;
#RegisterForReflection(targets = {
com.example.restapi.db.master.tables.pojos.TableA.class,
com.example.restapi.db.master.tables.pojos.TableB.class,
com.example.restapi.db.master.tables.records.TableA.class,
com.example.restapi.db.master.tables.records.TableB.class,
com.example.restapi.db.mdc.tables.pojos.TableC.class,
com.example.restapi.db.mdc.tables.pojos.TableD.class,
com.example.restapi.db.mdc.tables.records.TableC.class,
com.example.restapi.db.mdc.tables.records.TableD.class
})
public class JooqReflectionConfig {
}

You can do that with a Quarkus extension, get classes from the index and produce a ReflectiveClassBuildItem for all classes matching the package.
It's not that hard but requires a bit of work.
A less verbose alternative to what you're doing is to use #RegisterForReflection(targets = { ... }).
That's the only alternatives right now.

The cleanest solution seems to be writing a Quarkus extension.
Or, if you don't want to list RegisterForReflection targets manually, another possibility is to have reflection-config.json generated externally (probably using annotation processor? or maven/gradle task).

Related

Adding custom rules in Solhint

I am using solhint plugin for linting solidity code. But I want to add custom rules for the code analysis. How to add custom rules as part of the ruleset ?
Code added for custom rule:
const BaseChecker = require('./../base-checker')
const ruleId = 'no-foos'
const meta = {
type: 'naming',
docs: {
description: `Don't use Foo for Contract name`,
category: 'Style Guide Rules'
},
isDefault: false,
recommended: true,
defaultSetup: 'warn',
schema: null
}
class NoFoosAllowed extends BaseChecker {
constructor(reporter) {
super(reporter, ruleId, meta)
}
ContractDefinition(ctx) {
const { name } = ctx
if (name === 'Foo') {
this.reporter.error(ctx, this.ruleId, 'Contracts cannot be named "Foo"')
}
}
}
module.exports = NoFoosAllowed
I have saved the above code into a new js file inside rules->naming folder. And i have used the 'no-foos' rule id inside my .solhint.json file inside the rules property.
{
"extends": "solhint:all",
"plugins": [],
"rules": {
"avoid-suicide": "error",
"avoid-sha3": "warn",
"no-foos" : "warn",
"var-name-mixedcase": "error"
}
}
Each ruleset loops through all rules and enables (or doesn't enable) it based on the rule metadata and the ruleset config.
So you can create a custom rule in the rules folder and set it a combination of metadata that your ruleset will enable.

overriding js file in odoo9

In mail/static/src/js/thread.js i need to change display_reply_icon: false, to True
so overriding JS is kinda more difficult for me because i'm realy new to, so looking for help.
as my thought process is i need to create model find this js script with Xpath and then override with my own js file.
init: function (parent, options) {
this._super.apply(this, arguments);
this.options = _.defaults(options || {}, {
display_order: ORDER.ASC,
display_needactions: true,
display_stars: true,
display_document_link: true,
display_avatar: true,
shorten_messages: true,
squash_close_messages: true,
display_reply_icon: false,
});
this.expanded_msg_ids = [];
this.selected_id = null;
},
You have to load your js after the other js and then overwrite the init function.
To overwrite a function you can use extends() method.
https://www.odoo.com/documentation/9.0/reference/javascript.html

Extending lib.d.ts interfaces?

I have some code that handles a drop event and checks if I have to deal with dropped files:
public handleDrop(evt: DropEvent): boolean {
var isUpload: boolean; = false;
var dt: DataTransfer = evt.DataTransfer;
dt.types.forEach((type)=>{
// dt.types is of type DOMStringList
if(type === "File"){
isUpload = true;
}
})
return isUpload;
}
It works just as it is supposed to be, but the TS-compiler gives me following error message:
(117,16): error TS2339: Property 'forEach' does not exist on type 'DOMStringList'.
First of all, DataTransfer.types will always be an array, so in my understanding I should have access to its array methods.
I tried to create a workaround for my problem, by merging a custom DOMStringList Interface to the one defined in my lib.d.ts:
declare interface DOMStringList {
forEach(cb: Function): any;
}
IntelliJ recognizes the interface and does not show me an error for dt.types.forEach anymore.
However my ts-compiler still throws an error and does not seem to recognize my merged interface.
What is the proper way to tell my ts-compiler that I should be able to use array functions on an DOMStringList?
The problem occurs for other generic types like FileList as well.
EDIT:
ts.config.ts:
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"noEmitOnError": false,
"noImplicitAny": false,
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": true
},
"files": [
"app/typings/app.typings.ts",
"typings/tsd.d.ts"
]
}

i18next - All languages in one .json file

How can I make i18next load all languages from just one file?
I managed to do it by putting each language in a seperate file (translation-en.json, translation-no.json, etc), and also managed to input languages with the resStore option, but putting it all in a seperate .json file is really not documented anywhere (I've searched for 4 hours+ now)
My js code:
i18n.init({
debug: true,
lng: 'en',
resGetPath: 'translation.json'
},
function(t) {
console.log(t('test'));
});
My translation.json file:
{
en: {
translation: {
test: "some string"
}
},
no: {
translation: {
test: "litt tekst"
}
}
}
Ok, so I managed to "hack" it byt putting an object into a seperate .js file, include it in a script tag and loading it using resStore, but that just can't be the best way to use this lib.
Assume that your translation.json has loaded and assigned to a variable named resStore:
var resStore = {
en: {
translation: {
test: "some string"
}
},
no: {
translation: {
test: "litt tekst"
}
}
};
Next, you can override default ajax loading functionality with your customLoad function. An example might look like this:
var options = {
lng: 'en',
load: 'current',
lowerCaseLng: true,
fallbackLng: false,
resGetPath: 'i18n/__lng__/__ns__.json',
customLoad: function(lng, ns, options, loadComplete) {
var data = resStore[lng][ns];
loadComplete(null, data); // or loadComplete('some error'); if failed
},
ns: {
namespaces: ['translation'],
defaultNs: 'translation'
}
};
i18n.init(options, function(t) {
t('test'); // will get "some string"
});
new update on Mar 20, 2015
You can simply pass your resource store with the resStore option:
i18n.init({ resStore: resources });

Issue with the Textarea Readonly when using "wysihtml5" of bootstrap

I have tried to make the text area readonly in MVC4 Application.
But it is always being enable to edit when i use below code:
#Html.TextAreaFor(model => model.EndUserHelp, new { id = "name1", #class = "editorHelp"})
$('#name1').wysihtml5({
"font-styles": true,
"emphasis": true,
"lists": true,
"html": false,
"link": true,
"image": true,
"color": false,
"useLineBreaks": true
});
$("#name1").prop('readonly', true);
unable to make the area readonly.
You can add the following code where you initialize the editor.
I had the same issue with version 0.3.0 and made this to fix it.
function enforceInactiveStates() {
var disabled = this.textareaElement.disabled;
var readonly = !!this.textareaElement.getAttribute('readonly');
if (readonly) {
this.composer.element.setAttribute('contenteditable', false);
this.toolbar.commandsDisabled = true;
}
if (disabled) {
this.composer.disable();
this.toolbar.commandsDisabled = true;
}
}
editor.on( 'load', enforceInactiveStates );
Note that 'readonly' is different from 'disabled'.
Try this:
$editor = $(".textarea-disabled").wysihtml5();
$editor.attr('disabled', 'disabled');
Use 'disabled' not 'readonly'