Config variable not being fetched as expected from application.yml - grails-3.1

I have config variable(in application.yml) as:
xyz:
exception.emails: ['abc#gmail.com']
While fetching this in local works fine but after deploying war I am getting config variable as:
xyz: [
exception: [
emails[
0
]: abc#gmail.com
]
]
I am pulling this as:
def email = Holders.config.grails.xyz.exception.emails

I'm actually surprised this work at all, because I don't think that is proper yml syntax looking at the default application.yml they specify a list of userAgents like this:
grails:
mime:
disable:
accept:
header:
userAgents:
- Gecko
- WebKit
- Presto
- Trident
Personally I like to use an application.groovy and use groovy syntax like this:
grails {
mime {
disable {
accept {
header {
userAgents:
['Gecko', 'WebKit', 'Presto', 'Trident']
}
}
}
It maybe a little out of date but here is an example of a application.yml converted to application.groovy:
https://github.com/virtualdogbert/Grails3Tutorial/blob/step_01_settings_yml_to_groovy/grails-app/conf/application.groovy
Also note in the past you could run code from application.groovy, however if you have any imports they won't work,because application.yml/groovy, is meant for the cli(pre runtime), so as a workaround you can also specify a runtime.groovy, where you can have imports. If you ever go the extra mile and write a plugin, you can specify a plugin.groovy, to set defaults.

Related

react-i18next with multiple translation-files

I have a little problem in my application.
I use i18next and react-i18next for the translation and have already included it.
The whole translation comes from 1 file for each language and that is a mess with over 4000 rows :(
Now I want update this so that i18next would take the translation files placed in the different component-folders and their children-folders.
The folder-structure should look like this after the update:
scr
- components
-- Header
---translations (en/translation.json, de/translation.json)
-- Dashboard
--- translations (en/translation.json, de/translation.json)
--- Menu
---- translations (en/translation.json, de/translation.json)
---- ExampleComponent.tsx
---- ...
--- Cards
---- translations (en/translation.json, de/translation.json)
...
I already figured out how I can handle the automatic export via babel and babel-i18next-plugin with the "namespace"
So, my code (example Menu) would be written like this:
const { t } = useTranslation("Dashboard/Menu")
const explString = t("ExampleComponent.ExampleString","This is an example")
In babel I placed the plugin like this:
[i18next-plugin, {"outputPath": "src/components/{{ns}}/translations/{{locale}}/translation.json"}]
This runs without problems. It takes the namespace as a folder-structure and places the translation-files into the translation-folder including the correct keys.
Now, how I can tell i18next, where to find the translation-files?
I could only figure out that I can import the files (file-by-file) inside a resource.
I tried backend plugins (html-backend, async-storage-backend, local-storage-backend and filesystem) with
backend: { loadPath: "components/{{ns}}/translations/{{lng}}/translation.json" }
(The i18next.ts is placed inside src/)
and I get the warnings that the keys aren't found.
Also, you can see that I use TypeScript.
In my webpack I tried it with the ts-i18next-loader with this inside the webpack configuration file:
{
test: /\translation.json$/,
exclude: /node_modules/,
loader: 'i18next-ts-loader',
options: {
localeFilesPattern: 'src/components/{{ns}}/translations/{{lng}}/translation.json',
},
},
If I only had 5-6 translation-files for each language / namespace it would not be a problem to put it inside the resource but at the end I have more than 100 files for each language.
Would be nice if anyone had a solution to my problem. If you need any further information I can update the post.
Cheers
There's an alternative plugin to be used, suggested in the official documentation: https://www.i18next.com/how-to/add-or-load-translations#lazy-load-in-memory-translations
i18next-resources-to-backend helps to transform resources to an i18next backend. This means, you can also lazy load translations, for example when using webpack:
import i18next from 'i18next';
import resourcesToBackend from 'i18next-resources-to-backend';
i18next
.use(resourcesToBackend((language, namespace, callback) => {
import(`./locales/${language}/${namespace}.json`)
.then((resources) => {
callback(null, resources)
})
.catch((error) => {
callback(error, null)
})
}))
.init({ /* other options */ })
Found the solution.
After i included the "webpack backend for i18next" it solved the problem and the translation gets the correct file.
i18next webpack backend by SimeonC

TypeScript with Relay: Can't resolve generated module

In my MessageItem.tsx component I have the following code:
const data = useFragment(
graphql`
fragment MessageItem_message on Message {
date
body
}
`,
message as any
);
After running relay-compiler --src ./src --schema ../../schema.graphql --language typescript --artifactDirectory ./src/__generated__, a module named MessageItem_message.graphql.ts gets generated.
But when I run the app it gives me an error:
Failed to compile.
./src/components/MessageItem.tsx
Module not found: Can't resolve
'./__generated__/MessageItem_message.graphql'
The reason is only components at the src root can refer to the right path (./__generated__), whereas components in a folder actually need to refer to the path (../__generated__) but it's not doing so.
How can I configure the path?
Edit .babelrc to point to the artifactDirectory
// .babelrc
{
"plugins": [
[
"relay",
{
"artifactDirectory": "./src/ui/graphql/types"
}
]
]
}
Remove "--artifactDirectory ./src/__generated__" from the relay-compiler options.
By default it seems the Relay compiler puts a "__generated__" directory in the directory with any source code containing GraphQL.
As a result any "./__generated__" references anywhere and at any level in the source code hierarchy now work as they should.
Thanks to #ThibaultBoursier for the pointer.
PS I wonder if the --artifcactDirectory option is just meant to be used to change the name of the artifact directory, rather than its location?
Just moments ago I ran into the same issue. The reason is that the relay-compiler is using the artifactDirectory setting to decide where to put the generated files, but the babel-plugin-relay exposing the graphql tag needs to get the very same argument otherwise it just attempts to include a colocated relative file.
I fixed it in my case by configuring the plugin with a babel-plugin-macros.config.js file as follows (where the artifactDirectory is the same as the one supplied to the relay-compiler):
module.exports = {
relay: {
artifactDirectory: "./src/ui/graphql/types",
},
};
This solution assumes you are using the macro via babel-plugin-macros, otherwise you might need to supply that argument via the .babelrc file but I have no experience with that unfortunately.

sw-precache with angularJs application not caching

I am newbie to service worker concept so forgive me if I am overlooking something from documentation. I have an angular application already running in production and I am trying to introduce service worker using sw-precache.
To start with I am trying to precache all images/fonts and couple of js files and see if it works, so my precache config is like this -
{
"cacheId": "static-cache",
"importScripts": [
"sw-toolbox.js"
],
"stripPrefix": "dist/",
"verbose": true,
"staticFileGlobs": [
"dist/img/**.*",
"dist/javascripts/require.js",
"dist/stylesheets/**.*",
"dist/webfonts/**.{ttf, eot, woff}",
"sw-toolbox.js",
"service-worker.js"
]
}
Now I can see service worker registered and installed properly and cache storage shows all the urls with _sw-precache hashes.
But when I load the application and see in network tab all static content are still served from memory/disk, not from service worker and I am unable to debug why is it so. Am I missing something here -
UPDATE:
More information: I had wrong configurations since I have dynamic url and server side rendered html. Server side it's test.jsp which is giving me initial shell.
For now I have removed all other static files from cache and kept only show.css
So update config now is -
{
"importScripts": [
"sw-toolbox.js"
],
"stripPrefix": "dist/",
"verbose": true,
"staticFileGlobs": [
"dist/stylesheets/show.css"
],
"dynamicUrlToDependencies": {
"/developers": ["dist/stylesheets/show.css"]
},
"navigateFallback": "/developers"
}
Web root folder is named differently and it is -
- dashboard
-- img
-- javascripts
-- service-worker.js
-- sw-toolbox.js
- test.jsp
And I see /developers url as an entry in storage cache, but still it's not served from service worker for next refresh. I have tried all my energy to fix this, but I desperately need some clue here, what's missing in here. TIA.
Let me know if need more info.
It seems that whitespaces in your file extension list are not allowed. Your definition for webfonts should be:
"dist/webfonts/**.{ttf,eot,woff}",
I cloned the sw-precache repo and added a unit test where I compared two generated files with two diffrent staticFileGlobs, one with whitespace and one without.
it('should handle multiple file extensions', function(done) {
var config = {
logger: NOOP,
staticFileGlobs: [
'test/data/one/*.{txt,rmd}'
],
stripPrefix: 'test'
};
var configPrime = {
logger: NOOP,
staticFileGlobs: [
'test/data/one/*.{txt, rmd}'
],
};
generate(config, function(error, responseString) {
assert.ifError(error);
generate(configPrime, function(error, responseStringPrime) {
assert.ifError(error);
console.log('responseStringPrime',responseString);
assert.strictEqual(responseString, responseStringPrime);
done();
});
});
});
and it failed. The second config didn't include the .rmd file:
-var precacheConfig = [["/data/one/a.rmd","0cc175b9c0f1b6a831c399e269772661"],["/data/one/a.txt","933222b19ff3e7ea5f65517ea1f7d57e"],["/data/one/c.txt","fa1f726044eed39debea9998ab700388"]];
versus
+var precacheConfig = [["test/data/one/a.txt","933222b19ff3e7ea5f65517ea1f7d57e"],["test/data/one/c.txt","fa1f726044eed39debea9998ab700388"]];

Parsing application.yml in angularjs

I have a application.yml file in my application
spring:
profiles:
active: default,dev
app:
properties:
lucene:
indexInfoFile: ${spring.jpa.properties.hibernate.search.default.indexBase}/index.properties
reindex: false
storage:
home: ${user.home}/xxx
basePath: ${app.properties.storage.home}/uploads/
staticFilesPrefix: /files/
appUrl: /app/
spring:
profiles: dev
http:
multipart:
max-file-size: 3MB
max-request-Size: 3MB
Now in my controller, I am trying to get the data from yml file and the code for the same is
$http.get('/resources/application.yml').then(function (response) {
console.log('entire data is ', response.data);
console.log('basePath is ', response.data.basePath);
});
Entire Data is printing perfectly ( the whole yml file is getting printed) but when ever I am trying to print a particular property like basePath, max-file-size etc I am getting "undefined error".
My question is how to get a particular property to be printed on the console.
I would not recommend to access the yml file directly in Angular.
The format is difficult to parse (hence your question) and you sooner or later you may not want to expose all your confguration details.
Instead create a rest controller in spring mapped to something like /config
Let spring inject all the configuration values you need using #Value and return a Map or a simple PoJo with exactly the attributes you need.
Spring will convert this to JSON which you can easily be consumed in Angular.

Paypal SDK Class Name Conflicts

I want to use Paypal Adaptive Payments and Paypal Adaptive Accounts libs in my CakePHP 2.4.x application. I am loading them via composer. My composer.json file looks like this:
{
"require": {
"paypal/adaptivepayments-sdk-php":"v3.6.106",
"paypal/adaptiveaccounts-sdk-php":"v3.6.106"
},
"config": {
"vendor-dir": "Vendor"
}
}
Both libs contain Paypal/Types/Common/RequestEnvelope.php and for each lib they are different. I'm running into a conflict with this class name where the right one isn't being used. I believe the solution is to use autoload in my composer.json. I've read the documentation and don't believe I'm using it correctly. Here is what I'm attempting:
{
"require": {
"paypal/adaptivepayments-sdk-php":"v3.6.106",
"paypal/adaptiveaccounts-sdk-php":"v3.6.106"
},
"config": {
"vendor-dir": "Vendor"
},
"autoload": {
"psr-4": {
"AdaptivePaymentsLib\\": "Vendor/paypal/adaptivepayments-sdk-php/lib",
"AdaptiveAccountsLib\\": "Vendor/paypal/adaptiveaccounts-sdk-php/lib"
}
}
}
And in my controller I'm attempting to call RequestEnvelope like this:
$requestEnvelope = new AdaptivePaymentsLib\PayPal\Types\Common\RequestEnvelope("en_US");
It is not being found. Active Accounts was only recently added to the project. Previously getting the request envelope worked fine with $requestEnvelope = new PayPal\Types\Common\RequestEnvelope("en_US"); so it was only with the addition of the accounts which presented the conflict and caused the breakage.
You should not define autoloading for your dependencies - that is the task for them to solve.
If you look at the composer.json file for paypal/adaptivepayments-sdk-php, you see:
"autoload": {
"psr-0": {
"PayPal\\Service": "lib/",
"PayPal\\Types": "lib/"
}
}
If you look at the same file in paypal/adaptiveaccounts-sdk-php, you see:
"autoload": {
"psr-0": {
"PayPal\\Service": "lib/",
"PayPal\\Types": "lib/"
}
}
After installing, Composer creates a file vendor/composer/autoload_namespaces.php with this content:
return array(
'PayPal\\Types' => array($vendorDir . '/paypal/adaptivepayments-sdk-php/lib', $vendorDir . '/paypal/adaptiveaccounts-sdk-php/lib'),
'PayPal\\Service' => array($vendorDir . '/paypal/adaptivepayments-sdk-php/lib', $vendorDir . '/paypal/adaptiveaccounts-sdk-php/lib'),
'PayPal' => array($vendorDir . '/paypal/sdk-core-php/lib'),
);
So both libraries are included here, and I have no doubt the autoloading will work.
You cannot really do something about the duplicate classes with different content. Did you open an issue on Github? Without making the developer team aware of this problem, it will never get solved.
As a hack, you could define a post-install and post-update script that deletes one of these files. See the composer documentation for more details. Composer accepts either any shell command, or a static call to a PHP class. I'd go with the shell command here.

Resources