I want to make a post to an url with SSL validation in Grails.
I've imported the certificates, and I've generated the jks files.
But it seems Grails does not found those jks files.
Below is the code I'm executing (it's in a Grails Service Class):
def certificate = "mycert.jks"
def http = new HTTPBuilder(url)
def keyStore = KeyStore.getInstance(KeyStore.defaultType)
getClass().getResource(certificate).withInputStream {
keyStore.load(it, "test1234".toCharArray())
}
http.client.connectionManager.schemeRegistry.register(new Scheme("https", new SSLSocketFactory(keyStore), 443))
The error is
"Cannot invoke method withInputStream() on null object"
so
the method getResource() is not working, and returns null.
I saw that this code, in a functionalTest Class, works fine.
Anyone knows how can I solve this problem?
Thanks!!!!!!!
The problem is that non-source files from grails-app/services aren't copied into the classpath. This is the case for src/java though, but not src/groovy. It's also the case for grails-app/conf, but that's the only grails-app folder that this happens for, since it's the configuration file folder.
So your best bet is to move the file to grails-app/conf and use
Thread.currentThread().contextClassLoader.getResource(certificate).withInputStream {
keyStore.load(it, "test1234".toCharArray())
}
Related
I am using Json views plugin of grails. Which works in development, but when I run it as a jar file, it is not able to find the templates/gson files for rendering. I get the following error
//code
def template = jsonViewTemplateEngine.resolveTemplate(<path to template>)
def writable = template.make(kase: kase)
//exception
Cannot invoke method make() on null object. Stacktrace follows:
java.lang.NullPointerException: Cannot invoke method make() on null object
Json Views we are using are a part of a inline plugin we are developing. Jar we create also runs with that inline plugin (implemented using gradle wrapper)
Any ideas/suggestions?
Environment:
Grails - 3.2.0
Groovy - 2.4.7
Json-Views plugin - 1.1.1
Views are pre-compiled into classes for deployment via Gradle and the compileGsonViews task. This is done using the project.name setting by default.
You will notice in the build/main/gson-classes directory the classes that are produced. For example if your application name is foo you will have classes like foo_book_show_gson.class where the foo_ part is considered the "package" name.
At runtime. The package name to use to resolve views calculated from the info.app.name setting in grails-app/conf/application.yml.
What this means is that if in Gradle your project.name evaluates to foo and the setting in application.yml is also foo then all is well. This is the most common case as typically your application name is the same in both places.
If info.app.name and the Gradle project.name don't match up you can get the problem where views don't resolve.
You have two options to fix this. One is to modify build.gradle to explicitly specify the package name:
compileGsonViews.packageName = 'foo'
Then make sure info.app.name matches that value.
The second option is rename your project directory so that info.app.name and project.name align.
Json View behavior is different in dev mode and war mode.
WritableScriptTemplate template
if (Environment.isDevelopmentEnvironmentAvailable()) {
template = attemptResolvePath(path)
if (template == null) {
template = attemptResolveClass(path)
}
} else {
template = attemptResolveClass(path)
if (template == null) {
template = attemptResolvePath(path)
}
}
if (template == null) {
template = NULL_ENTRY
}
In development mode grails will load your template by file path first then load by class name.
If you are working on case insensitive file system,template file like
'your_template_name' and 'YOUR_TEMPLATE_NAME' will be treated same.
But class name is case sensitive,'your_template_name_class' and 'YOUR_TEMPLATE_NAME_CLASS' is different;
Maybe your template file name is incorrect.
For example, if your classname is:
QueryResult
Your template file should located in:
/views/queryResult/_queryResult.gson
Json View will search class like:
<Project-Name>_queryResult__queryResult_gson
To read a properties file in JSF2.0 with Glassfishv3 webserver, which is located at root directory of my web application, I am using below code-
ServletContext ctx = (ServletContext) FacesContext
.getCurrentInstance().getExternalContext().getContext();
String deploymentDirectoryPath = ctx.getRealPath("/");
Properties prop = new Properties();
prop.load(new FileInputStream(deploymentDirectoryPath
+ File.separator + "portal-config.properties"));
Below is the screenshot of web portal-
While running the portal I am getting FileNotFound Error, since the file is not present in glassfish domain.
Is there any way to read properties file which can work in both the situations, at development stage and in war file also?
You should never use java.io.File to refer web resources. It knows nothing about the context it is sitting in. You should also never use ServletContext#getRealPath() as it may return null when the server is configured to expand WAR file in memory instead of on disk, which is beyond your control in 3rd party hosts.
Just use ExternalContext#getResourceAsStream() to get the web resource directly in flavor of an InputStream. It takes a path relative to the webcontent root.
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
properties.load(ec.getResourceAsStream("/portal-config.properties"));
See also:
getResourceAsStream() vs FileInputStream
What does servletcontext.getRealPath("/") mean and when should I use it
Where to place and how to read configuration resource files in servlet based application?
Update it does not seem to be a web resource at all. You should move the file into the "WebContent" folder as shown in the screenshot. Or, better, the /WEB-INF folder so that nobody can access it by URL.
properties.load(ec.getResourceAsStream("/WEB-INF/portal-config.properties"));
An alternative would be to put it in the classpath, the "Java source" folder as shown in the screenshot. You don't need to put it in a package, that's optional. Assuming that you didn't put it in a package, then do so:
ClassLoader cl = Thread.currentThread().getContextClassLoader();
properties.load(cl.getResourceAsStream("portal-config.properties"));
(note that the path may not start with a slash!)
As I am trying to write a Grails Plugin, I stumbled upon two problems:
how do I modify one of the configuration files like Config.groovy or DataSource.groovy from witin the _install.groovy script? It is easy to append something to those files, but how do I modify it in a clean way? text.replaceAll()? Or should I create a new config file?
how do I get the name of the current application into which the plugin will be installed? I tried to use app.name and appName but both do not work.
Is there maybe somewhere a good tutorial on creating plugins which I haven't found yet?
Here is an example of editing configuration files from scripts/_Install.groovy.
My plugin copies three files to the target directory.
.hgignore is used for version control,
DataSource.groovy replaces the default version, and
SecurityConfig.groovy contains extra settings.
I prefer to edit the application's files as little as possible, especially because I expect to change the security setup a few years down the road. I also need to use properties from a jcc-server-config.properties file which is customized for each application server in our system.
Copying the files is easy.
println ('* copying .hgignore ')
ant.copy(file: "${pluginBasedir}/src/samples/.hgignore",
todir: "${basedir}")
println ('* copying SecurityConfig.groovy')
ant.copy(file: "${pluginBasedir}/src/samples/SecurityConfig.groovy",
todir: "${basedir}/grails-app/conf")
println ('* copying DataSource.groovy')
ant.copy(file: "${pluginBasedir}/src/samples/DataSource.groovy",
todir: "${basedir}/grails-app/conf")
The hard part is getting Grails to pick up the new configuration file. To do this, I have to edit the application's grails-app/conf/Config.groovy. I will add two configuration files to be found on the classpath.
println ('* Adding configuration files to grails.config.locations');
// Add configuration files to grails.config.locations.
def newConfigFiles = ["classpath:jcc-server-config.properties",
"classpath:SecurityConfig.groovy"]
// Get the application's Config.groovy file
def cfg = new File("${basedir}/grails-app/conf/Config.groovy");
def cfgText = cfg.text
def appendedText = new StringWriter()
appendedText.println ""
appendedText.println ("// Added by edu-sunyjcc-addons plugin");
// Slurp the configuration so we can look at grails.config.locations.
def config = new ConfigSlurper().parse(cfg.toURL());
// If it isn't defined, create it as a list.
if (config.grails.config.locations.getClass() == groovy.util.ConfigObject) {
appendedText.println('grails.config.locations = []');
} else {
// Don't add configuration files that are already on the list.
newConfigFiles = newConfigFiles.grep {
!config.grails.config.locations.contains(it)
};
}
// Add each surviving location to the list.
newConfigFiles.each {
// The name will have quotes around it...
appendedText.println "grails.config.locations << \"$it\"";
}
// Write the new configuration code to the end of Config.groovy.
cfg.append(appendedText.toString());
The only problem is adding SecurityConfig.groovy to the classpath. I found that you can do that by creating the following event in the plugin's /scripts/Events.groovy.
eventCompileEnd = {
ant.copy(todir:classesDirPath) {
fileset(file:"${basedir}/grails-app/conf/SecurityConfig.groovy")
}
}
Ed.
You might try changing the configuration within the MyNiftyPlugin.groovy file (assuming that your plugin is named my-nifty). I've found that I can change the configuration values within the doWithApplicationContext closure. Here's an example.
def doWithApplicationContext = { applicationContext ->
def config = application.config;
config.edu.mycollege.server.name = 'http://localhost:8080'
config.edu.mycollege.server.instance = 'pprd'
}
The values you enter here do show up in the grailsApplication.config variable at run time. If it works for you, it will be a neater solution, because it doesn't require changes to the client project.
I must qualify that with the fact that I wasn't able to get Spring Security to work by this technique. I believe that my plugin (which depends on Spring Security) was loaded after the security was initialized. I decided to add an extra file to the grails-app/conf directory.
HTH.
For modifying configuration files, you should use ConfigSlurper:
def configParser = new ConfigSlurper(grailsSettings.grailsEnv)
configParser.binding = [userHome: userHome]
def config = configParser.parse(new URL("file:./grails-app/conf/Config.groovy"))
If you need to get application name from script, try:
metadata.'app.name'
Grails 1.3.7
I have some configuration located in an external config file. One of the entires looks like this:
site.maintenance.mode = false
I have a filter which checks for certain config settings for specific URLs. When I do a run-app or deploy a WAR into Tomcat and do:
boolean maintenanceMode = grailsApplication.config.site.maintenance.mode
maintenanceMode is coming back true. If I look at the config object in debug mode, this is what I get:
site={maintenance={mode=false, message="<p>Our trail guides are working hard to get the system back on track.</p><p>We're sorry, the account system is down for maintenance at the moment. We'll get it back online as quickly as we can. Thanks for your patience.</p>"}}
I have a controller that I use to reload this config file dynamically and hitting this controller will fix the issue. But I'm curious as to why it is incorrect on first runs and why the discrepency in what is getting put in the maintenanceMode variable vs what is actually in the config object.
Are you using a Java properties file or a Groovy file? If you're using a properties file then I believe Grails will interpret site.maintenance.mode=false the same way as site.maintenance.mode='false' and since Groovy will interpret:
"false".asBoolean() == true
then that would explain why you would see that initial true value.
I just ran a simple test locally to verify this behavior. When I externalize my properties in a file called test.properties then site.maintenance.mode=false initially gets a boolean value of true, when I use a file called test.groovy then it interprets the boolean value of site.maintenance.mode=false as false. I believe this is because when you use a Groovy file Grails uses ConfigurationSlurper to process it but when you use a properties file Grails interprets everything as String name/value pairs.
What I do is to have an external Config.groovy file, for instance: MyConfig.groovy
At the end of the standard grails Config.groovy file, I have the following:
def ENV_NAME = "MY_EXTERNAL_CONFIG"
if(!grails.config.locations || !(grails.config.locations instanceof List)) {
grails.config.locations = []
}
if(System.getenv(ENV_NAME)) {
grails.config.locations << "file:" + System.getenv(ENV_NAME)
} else if(System.getProperty(ENV_NAME)) {
grails.config.locations << "file:" + System.getProperty(ENV_NAME)
} else {
println "No external Configs found."
}
So now you can have a MyConfig.groovy file anywhere in production environment (for example) and then set an Environment system variable to point to this file (or pass it as parameter to startup.sh), before you start tomcat:
MY_EXTERNAL_CONFIG="/home/tomcat/configs/MyConfig.groovy"
export MY_EXTERNAL_CONFIG
That's it. Now you have an external MyConfig.groovy file. The properties in it are accessible from your grails app as they were part of the standard Config.groovy
import org.codehaus.groovy.grails.commons.*
//...
ConfigurationHolder.config.foo.bar.hello
Hypothetical situation:
I have downloaded a Grails application from the web as a WAR file, foo.war. In the documentation it says that I can put my own custom configuration in /foo.groovy, because this path is included in grails.config.locations in Config.groovy. I can dump all my custom config in that one file and life is good.
How, here's my problem... The configuration for FooApp is big and hairy, and I don't want it all in one file. I would like to break it up into /bar.groovy and /baz.groovy to keep things organized. Is there a way to specify something in /foo.groovy so that FooApp will also pick up /bar.groovy and /baz.groovy and process them?
I already tried appending paths to grails.config.locations in /foo.groovy, but Grails didn't like that and threw a nasty exception on startup. I'm not sure what other approach to take.
Edit for clarity:
grails-app/conf/Config.groovy looks like this:
grails.config.locations = ["file:/foo.groovy"]
Now, without modifying grails-app/conf/Config.groovy, and only by modifying /foo.groovy, is there a way to load more config files other than /foo.groovy?
You could slurp the additional config files within foo.groovy:
foo.groovy
port {
to {
somewhere=8080
another {
place=7070
}
}
}
host = new ConfigSlurper().parse(new File("bar.groovy").toURL())
bar.groovy
to {
somewhere="http://localhost/"
another {
place="https://another.place.com/"
}
}
So within your app you have:
assert grailsApplication.config.port.to.somewhere == 8080
assert grailsApplication.config.port.to.another.place == 7070
assert grailsApplication.config.host.to.somewhere == "http://localhost/"
assert grailsApplication.config.host.to.another.place == "https://another.place.com/"