Could some wise guru give me a hand to get the Cache Plugin to work? I have been given this project that uses:
Grails 3.3.0
gradle 3.0
GORM 6.1.6.Release
Cache Plugin 4.0.0
I'm following https://grails-plugins.github.io/grails-cache/snapshot/guide/index.html#usage to enable Caching though the app can be started without error, the method that is annotated by #Cacheable doesn't seem to be caching. This is what my myWebApp**build.gradle** looks like:
:
compile group: 'org.grails.plugins', name: 'cache', version: '4.0.0'
compile group: 'org.grails.plugins', name: 'async'
:
This is my grails-app/conf/application.yml:
---
grails:
cache:
caches:
name: 'mycache'
---
This is how I enable cache in grails-app/conf/application.groovy:
:
grails.cache.enabled = true
grails.cache.clearAtStartup = true
:
This is my myWebApp/Application.groovy:
package myWebApp
:
class Application extends GrailsAutoConfiguration {
static void main(String[] args) {
GrailsApp.run(Application, args)
}
}
This is the method in a controller with #Cachable (grails-app/controllers/data/mycontroller.groovy):
package data
:
import org.springframework.cache.annotation.Cacheable
:
#Transactinal
class MyController {
:
#Cacheable(value='mycache')
def getSomeId() {
return anId
}
:
}
In the same controller, I am calling this method for quick test:
:
def index() {
def id = getSomeId()
:
}
:
The problem is getSomeId() didn't seem to be cached. Everytime getSomeId() was called, the body was executed in full length (I set a break point to verify). I just want to use a quick and simple cache mechanism for simple things like this.
What did I do wrong?
Thanks for all you folks, the cache finally works in my project. HOWEVER, the import for annotation must come from the plugin: grails.plugin.cache.Cacheable works, but org.springframework.annotation.Cacheable doesn't.
Related
I had a grails 3 app including spring security, which I recently upgraded to grails 4.
My application.yml includes the following:
environments:
test:
grails:
plugin:
springsecurity:
active: false
security:
ignored: '/**'
basic:
enabled: false
spring:
security:
enabled: false
Why doesn't this work in Grails 4? What's a good alternative solution?
Grails 4 seems to be ignoring this configuration. When I run integration tests, I am getting a 403 error with a message:
Could not verify the provided CSRF token because your session was not found.
It seems like spring security enabled, and it's using SecurityFilterAutoConfiguration, which is normally excluded for my app.
Update
I am using the following dependencies:
compile('org.grails.plugins:spring-security-core:3.2.3') {
exclude group: 'org.springframework.security'
}
compile ('org.springframework.security:spring-security-core:4.2.13.RELEASE') {
force = true
}
compile 'org.springframework.security:spring-security-web:4.2.13.RELEASE'
compile 'org.springframework.security:spring-security-config:4.2.13.RELEASE'
Update 2:
In my debugger, I found that the spring security core plugin actually is being disabled. The following code from the plugin class is executed:
SpringSecurityUtils.resetSecurityConfig()
def conf = SpringSecurityUtils.securityConfig
boolean printStatusMessages = (conf.printStatusMessages instanceof Boolean) ? conf.printStatusMessages : true
if (!conf || !conf.active) {
if (printStatusMessages) {
// <-- the code in this block is executed; active flag is false
String message = '\n\nSpring Security is disabled, not loading\n\n'
log.info message
println message
}
return
}
...however, I am still getting the CSRF filter error, so Spring Security must be configuring itself somehow regardless.
Update 3:
The CSRF filter is being set up by ManagementWebSecurityConfigurerAdapter, using the default configuration.
I tried adding the following to resources.groovy:
if (grailsApplication.config.disableSecurity == true && !Environment.isWarDeployed()) {
webSecurityConfigurerAdapter(new WebSecurityConfigurerAdapter(true) {})
}
This did not fix the issue. Although my anonymous WSCA bean is being constructed, the MWSCA default bean is still being used by spring.
Try this in
grails-app/conf/application.groovy
environments {
development {
}
test {
grails.plugin.springsecurity.active = false
}
production {
}
}
spring boot version: 2.0.4.RELEASE
asset-pipeline version: 3.0.3
Hi
we're using this plugin, because we know it from our grails applications.
We liked it, because it has a simple configuration (for our requirements)
Now we're developing a spring boot application and we used this plugin too and we're (almost) happy with it.
But when we run the application in the development mode the assets don't have a digest like /assets/my-styles-b5d2d7380a49af2d7ca7943a9aa74f62s.css
How do i configure the plugin to create a digest for all our resources?
currently we're using this configuration:
assets {
minifyJs = true
minifyCss = true
enableSourceMaps = false
includes = ["application.js", "application.scss"]
}
And we're using thymeleaf for our templates:
<link th:href="#{/assets/application.css}" rel="stylesheet">
I found a solution...
when you use the asset-pipeline, you get a gradle task assetCompile.
when creating a .war file, you can add this gradle task and replace all the assets with the versioned files.
when you want to use the versioned files in your production mode you have to use this configuration (build.gradle)
assets {
minifyJs = true
minifyCss = true
skipNonDigests = true
packagePlugin = true
includes = ["application.js", "application.scss"]
}
...
war {
dependsOn 'assetCompile'
from( "${buildDir}/assets", {
into "/WEB-INF/classes/META-INF/assets"
})
baseName = '<your project>'
enabled = true
}
that's all.
When running the assetCompile task, a manifest.properties file is created. This file contains the mapping of the original filename and the versioned one.
This file is used by the application to find the correct resource, e.g. application.css=application-79a3c8a2f085ecefadgfca3cda6fe3d12.css
I created a plugin which enables the url replacement for assets with digest in the production mode:
Dependency
compile 'ch.itds.taglib:asset-pipeline-thymeleaf-taglib:1.0.0'
Configuration
#Configuration
public class ThymeleafConfig {
#Bean
public AssetDialect assetDialect() {
return new AssetDialect();
}
}
Usage
<html xmlns:asset="https://www.itds.ch/taglib/asset">
<script asset:src="#{/assets/main.js}"></script>
</html>
The asset:src="#{/assets/main.js}" will be replaced with src="/assets/main-DIGEST.js".
The replacement happens only if the developmentRuntime of the asset pipeline is disabled.
A little bit more details are available on my blog post: https://kobelnet.ch/Blog/2019/03/12/assetpipelinethymeleaftaglib
So I just started learning Grails, and I am trying incorporate the Spring Security REST plugin into my app, the plugin is installed in addition to spring security core which is working. In my REST client, when I hit "api/login" I am able to get an access token and it says I have the role of "ROLE_ADMIN", but then when I try to hit something using that, I keep getting a 403 Forbidden. In Postman, the REST client I am using, I have my Authorization header with "Bearer {key}", with my url of "http://localhost:8080/test/api/secret" and it gives the 403 error. I am trying to setup the log4j logging to see any other issues, but does anyone know what I should look into, any help would be appreciated. I provided my classes below if that helps, I generally used default values for everything such as the UrlMappings.
RandomController.groovy
package test
import grails.plugin.springsecurity.annotation.Secured
#Secured(['IS_AUTHENTICATED_ANONYMOUSLY'])
class MyController {
#Secured(['ROLE_ADMIN'])
def secret() {
render "You have ACCESS!!!"
}
}
Bootstrap.groovy
class BootStrap {
def init = { servletContext ->
def adminRole = new SecRole(authority: 'ROLE_ADMIN').save(flush: true)
def testUser = new SecUser(username: 'bob', password: 'test')
testUser.save(flush: true)
SecUserSecRole.create testUser, adminRole, true
}
def destroy = {
}
}
UrlMappings.groovy
class UrlMappings {
static mappings = {
"/$controller/$action?/$id?(.$format)?"{
constraints {
// apply constraints here
}
}
"/api/$controller/$action?/$id?(.$format)?"{ constraints { // apply constraints here
} }
"/"(view:"/index")
"500"(view:'/error')
}
}
For what I can see from the code you posted, if you invoke url http://localhost:8080/test/api/secret, it should execute default action (maybe index) in SecretController but the controller you posted is called MyController.
To investigate further, you should enable more verbose logging using log4j configuration as suggested in the doc http://alvarosanchez.github.io/grails-spring-security-rest/1.5.1/docs/guide/debugging.html
I created a new project in Eclipse from these helpful spring examples (Import Getting Started Content). It is called "gs-accessing-data-rest-complete"
Reference and full Code can be found: spring-guides/gs-accessing-data-rest
When leaving the example unchanged, except using WAR instead of JAR packaging, everything works well. When calling $ curl http://localhost:8080/, I'll get an exposure of usable resources.
$ curl http://localhost:8080/
{
"_links" : {
"people" : {
"href" : "http://localhost:8080/name{?page,size,sort}",
"templated" : true
},
"profile" : {
"href" : "http://localhost:8080/alps"
}
}
But when moving the PersonRepository into another package, e.g. myRepos via Eclipse's Refactor-->Move command, a resource is not accessible anymore.
The response from curl is then:
$ curl http://localhost:8080/
{
"_links" : {
"profile" : {
"href" : "http://localhost:8080/alps"
}
}
}
As far as I understood, Spring scans for Repositories automatically. Because the main class uses #SpringBootApplication annotation, everything should be found by spring itself.
What am I missing? Do I have to add some special XML configuration file or add another Configuration Class somewhere? Or do I have to update application.properties in order to sth.?
Perhaps somebody has some useful experiences, she or he might share with me. Thank you.
Try specifying the base package to use when scanning for repositories by using this annotation on your config class: #EnableJpaRepositories(basePackages = "your.base.repository.package")
I’m running into an issue getting wss:// to work on version 3.06 in production.
I’ve been able to get it working in a test environment locally (see test environment settings at the end).
If I used ws:// and not wss://, the production server works
In production I get the following error: net::ERR_CONNECTION_REFUSED
(Note: when I use ws://, I’ve switched over my test web site to http:// and not https://
Production environment:
2 separate Web servers running a web application (load balanced)
1 separate server running XSockets v3.06 (as a Windows Service)
All servers are in a sub domain:
a. Web server: web1.acme.com
b. Xsocket Server: commbus.acme.com
(Note: I’m not showing the real domain name here (acme))
All servers are using the same wildcard certificate “cn=*.acme.com”
All servers are behind a firewall.
I’ve tried using a ConfigurationSettings class with the following different constructors:
(Note: the 192.168.1.1 is not the real internal IP we use but it’s similar)
1) I used this option because it worked in the test environment
public class SecureConfig : ConfigurationSetting
{
public SecureConfig()
: base()
{}
}
2)
public SecureConfig()
: base(new Uri("wss://commbus.acme.com:4502"), new Uri("wss://192.168.1.1:4502"))
{
this.CertificateLocation = StoreLocation.LocalMachine;
this.CertificateSubjectDistinguishedName = "cn=*.acme.com";
}
3)
public SecureConfig()
: base(new Uri("wss://commbus.acme.com:4502"), new Uri("wss://192.168.1.1:4502"))
{
4)
public SecureConfig()
: base(new Uri("wss://commbus.acme.com:4502")
{}
5)
public SecureConfig()
: base(new Uri("wss://commbus.acme.com:4502")
{
this.CertificateLocation = StoreLocation.LocalMachine;
this.CertificateSubjectDistinguishedName = "cn=*.acme.com";
}
Test environment:
To verify that I can setup wss://. I’ve been able to do the following test:
1) Run IIS Express locally with HTTPS
2) Run the XSockets code in a console application
(Note: All XSockets code is in a separate library assembly and the same library assembly is used in both my test console application and production)
3) For the test I used the certificate “cn=localhost”
This worked fine if I used the following in a ConfiguationSetting Class:
public class SecureConfig : ConfigurationSetting
{
public SecureConfig()
: base()
{
}
}
Behavior I’ve notice with the testing site:
I would get the same error in production if I used the following contructors for the ConfigurationSettings class:
public SecureConfig()
: base(new Uri("wss://localhost:4502"))
{
}
Or
public SecureConfig()
: base(new Uri("wss://localhost:4502"))
{
this.CertificateLocation = StoreLocation.LocalMachine;
this.CertificateSubjectDistinguishedName = "cn=local";
}
I’m not sure what I’m missing.
I was able to get it working.
I had to load the certificate from the file system.
public class SecuritConfig: ConfigurationSetting
{
public SecureConfig():base(new Uri("wss://commbus.acme.com"), new Uri("wss://192.168.1.100"))
{
this.Certificate = new X509Certificate2("wildcard.acme.com.pfx", "pwd");
}
}