In Grails latest version like 4 and 5, it provides static assets management mechanism more standard way. We can use different files under the corresponding folders. |
All the images will go under the images directory, js files go under the javascripts directory and CSS goes under the stylesheets directory. These files will be accessed by the URL path start with "/assets/". |
Now, what if you don't want to use this structure or need to use the root path for some static file content. |
For this, grails provide another option to manage static resources. So, what you can do is create the /resources/public directory under /src/main/ and use static resources there. |
For example, if you had a file under /src/main/resources/public/images/example.jpg path then you can access that file using https://example.com/static/images/example.jpg. |
This means, your file can be accessed with "/static/" URL by default.
If you want to access the file in the app root directory, setup the following configuration under application.groovy grails.resources.pattern = '/**' |
Now, for the above example the file can be accessed with https://example.com/images/example.jpg URL and if the file is in /public/ directory that file can be accessed with root path https://example.com/file.js |
Showing posts with label Grails. Show all posts
Showing posts with label Grails. Show all posts
Tuesday, October 4, 2022
How to use static content / resource files in app root directory in grails
Thursday, September 29, 2022
Tracking of Stackoverflow Exception from Grails / Gradle Project - Caused by: java.lang.StackOverflowError: null
In many cases we may face Stackoverflow exception and in my many cases I didn't find the exact point where this exception occurred. |
Then I start checked my debug output and found that from UrlMappingUtils.java class in package org.grails.web.mapping is the reason of StackoverflowException rather than throwing the main Exception. |
This is because of handling of Exception is not handled properly. |
Then I set a breakpoint inside method public static String forwardRequestForUrlMappingInfo and found the original Exception from there. |
Add resources and config files to your JAR using Gradle Build for Grails Application
How do I add config files or any other resources into my jar using gradle? How to include everything inside src/main/java to compile I have a project. Inside the project I have few files like x.properties, x.csv and many more under src/main/webapp package, I used gradle to compile, I didn’t see src/main/webapp directory in my build folder. How can I include everything to build? Because I need to include contents inside src/main/webapp directory to be include in my jar so that resources can be accessible by who will use my jar. |
So first step is to tell compiler to include files in jar file using below code snippet - Add below code snippet to build.gradle: sourceSets { main { resources { srcDir "src/main/webapp" include "*.properties" include "*.csv" exclude "*.png" exclude "a1" exclude "a2" srcDir "src/main/webapp/a1" exclude "**/*.text" include "**/*.csv" srcDir "src/main/webapp/a2" include "**/*.html" } } } |
My project structure is like below: |
And the files stored in the generated jar file as below: |
Now the process to use the resources file into the project, add below configuration to build.gradle file (which project will use jar created above): copy{ from(zipTree("path_to_jar_file/plain.jar")) into("./") include "src/main/webapp/**/*.*" [will extract all to root directory] include "src/main/webapp/kkk/*.*" [will extract all files in folder named kkk to root directory] } |
Above configuration will extract all file from (jar) "src/main/webapp" to projectRoot/src/main/webapp directory as below: |
Thursday, October 21, 2021
Grails 4: How to add Java JAR files to Grails project | How to add an external library or JAR file that is not a grails plugin to the Grails project
Putting the jar in the lib folder should do the trick.
The default lib folder is gone as of Grails 3.0. grails.github.io/grails-doc/3.0.x/guide/single.html#upgrading --> "Dependency resolution should be used to resolve JAR files" |
If Grails by default don't take the local .jar libraries located in <GRAILS-APP-DIR>/lib (seems that with Grails >= 3.X the /lib folder default configuration is removed) the easy way to enforce it is modifying build.gradle to add a local directory dependency for it. |
For almost all cases is of course better to use the maven repos, but in some cases it's possible to have some other libraries which aren't in a public repo. To do so we have to add these libraries in some lib folder then modify the <GRAILS-APP-DIR>/build.gradle and add something like: |
dependencies { ... // lib folder or any other name one can use compile fileTree(dir: './lib', include: ['*.jar']) ... } |
If you want you can use another directory (not /lib) since you're specifying it. Of course use the correct scope (for example for jars which probably already are in your application container class path the scope will be runtime instead of compile) |
You can download and drop the jar file into the grails-app/lib directory directly. This should be carefully maintained by someone time to time. Other developers working on the same project might not be aware of its presence. Plus you cannot easily upgrade versions in a transparent manner. |
Tuesday, October 12, 2021
Grails 4: How to load datasource configuration from external file in grails 4 In Grails, how do I put my DB username and password in an external property file
I'm trying to take certain database configurations from variables and put them into an external properties file.
I am writing a grails 4.0.11 application. My datasource written in application.groovy file. I want to load datasource configuration like username,password,DB from an external file. Is there any way to do it in grails 4+ versions. Here is my datasource configuration in application.groovy using static database name and other properties like username, password etc:- |
hibernate { cache { queries = false use_second_level_cache = true use_query_cache = true } } dataSource { pooled = true jmxExport = true dialect = "org.hibernate.dialect.MySQL5InnoDBDialect" driverClassName = "org.mariadb.jdbc.Driver" username = 'root' password = '' dbCreate = "update" url = "jdbc:mysql://localhost/db2?useUnicode=yes" + "&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true" + "&useLegacyDatetimeCode=false&serverTimezone=UTC" properties = { jmxEnabled = true initialSize = 5 maxActive = 50 minIdle = 5 maxIdle = 25 maxWait = 10000 maxAge = 10 * 60000 timeBetweenEvictionRunsMillis = 5000 minEvictableIdleTimeMillis = 60000 validationQuery = "SELECT 1" validationQueryTimeout = 3 validationInterval = 15000 testOnBorrow = true testWhileIdle = true testOnReturn = false ignoreExceptionOnPreLoad = true jdbcInterceptors = "ConnectionState;StatementCache(max=200)" defaultTransactionIsolation = Connection.TRANSACTION_READ_COMMITTED // safe default abandonWhenPercentageFull = 100 // settings are active only when pool is full removeAbandonedTimeout = 120 removeAbandoned = true logAbandoned = false // causes stacktrace recording overhead, use only for debugging } } |
Yes, what we can do that is to put database configurations to a file named db_name.properties under [src/main/webapp] directory with following contents:
db_name=some_data_base_name db_user=root_user db_password=some_password Keeping these information will not load automatically. We have to do something magic to load these information into system. We can define database configuration for grails 4 in 3 different ways - 1. grails-app/conf/config/application.yml 2. grails-app/conf/application 3. grails-app/conf/application.groovy So from above list we can easily set our target file to load grails 4 application datasource information because we can write code inside groovy files. First of all remove any datasource related block from above 2 files and add configuration to grails-app/conf/application.groovy file as early statement with some modification. Now we will load database information from some properties file. We sill use Properties to load database information from file. Check below code snippet: |
import grails.util.BuildSettings import java.sql.Connection grails { gorm { failOnError = true 'default' { mapping = { cache true version false autoTimestamp false id generator:'assigned' '*'(cascadeValidate: 'none') } } } } Properties ppt = new Properties() File file = new File(BuildSettings.BASE_DIR.absolutePath + "/src/main/webapp/db.properties") println("Setting up db name-${file.absolutePath}, exists=${file.exists() ? 1 : 0}") if (file.exists()) { file.getCanonicalFile().withInputStream { InputStream stream -> ppt.load(stream) } } println(ppt) hibernate { cache { queries = false use_second_level_cache = true use_query_cache = true } } dataSource { pooled = true jmxExport = true dialect = "org.hibernate.dialect.MySQL5InnoDBDialect" driverClassName = "org.mariadb.jdbc.Driver" username = 'root' password = '' dbCreate = "update" url = "jdbc:mysql://localhost/${ppt.get("db.name", "none_db_selected")}?useUnicode=yes" + "&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true" + "&useLegacyDatetimeCode=false&serverTimezone=UTC" properties = { jmxEnabled = true initialSize = 5 maxActive = 50 minIdle = 5 maxIdle = 25 maxWait = 10000 maxAge = 10 * 60000 timeBetweenEvictionRunsMillis = 5000 minEvictableIdleTimeMillis = 60000 validationQuery = "SELECT 1" validationQueryTimeout = 3 validationInterval = 15000 testOnBorrow = true testWhileIdle = true testOnReturn = false ignoreExceptionOnPreLoad = true jdbcInterceptors = "ConnectionState;StatementCache(max=200)" defaultTransactionIsolation = Connection.TRANSACTION_READ_COMMITTED // safe default abandonWhenPercentageFull = 100 // settings are active only when pool is full removeAbandonedTimeout = 120 removeAbandoned = true logAbandoned = false // causes stacktrace recording overhead, use only for debugging } } |
In above example I only set database name, you can set anything from that configuration file as I did for database name. |
Grails saves datetime as UTC time, but reads it as local server time
Grails saves datetime as UTC time, but reads it as local server time??? |
The timestamp is read back as local time instead. So if my timezone is +2 UTC and the current local time is 12:30:00, what will be saved to the database is 10:30:00, but when I read it back, it becomes 10:30:00. Does anybody know how to fix this problem so that Grails will read the timestamp back as UTC and convert it accordingly? |
I have the following line in my Grails application (BootStrap.groovy) to set the default timezone to UTC: |
TimeZone.setDefault(TimeZone.getTimeZone("UTC")) |
And above line solved my problem. Now I can set time anything to db and returned back the same date to my domain field |
Wednesday, September 29, 2021
GRAILS 4 - how to disable deepvalidate in grails globally | Add ability to control cascading validation independently
How can we disable deepvalidate on global level in grails 4? as in our case on saving one domain object its trying to save all internal domain objects leading to different errors like unique constraint and all.
If GORM entity references some other entities, then during its constraints evaluation (validation) the constraints of the referenced entity could be evaluated also, if needed. There is a special parameter cascadeValidate in the entity mappings section, which manage the way of this cascaded validation happens. You can do this in three ways |
1. Define cascadeValidate as mapping per domain where needed: class Author { Publisher publisher static mapping = { publisher(cascadeValidate: "none") } } class Publisher { String name static constraints = { name blank: false } } |
The following table presents all options, which can be used: none: Will not do any cascade validation at all for the association. default: The DEFAULT option. GORM performs cascade validation in some cases. dirty: Only cascade validation if the referenced object is dirty via the DirtyCheckable trait. If the object doesn’t implement DirtyCheckable, this will fall back to default. owned: Only cascade validation if the entity owns the referenced object. |
2. It is possible to set the global option for the cascadeValidate: Globally disable cascadeValidate in Grails 3 or 4 using: grails { gorm { failOnError = true 'default' { mapping = { cache true version false autoTimestamp false id generator:'assigned' '*'(cascadeValidate: 'none') // this one is the option to disable deep validate } } } } |
3. Alternatevely you can disable when call save() or merge() using: new Account().save(validate: true, deepValidate: false) |
Grails gorm reference link: Reference https://gorm.grails.org/latest/hibernate/manual/#_cascade_constraints_validation |
Sunday, October 18, 2020
Grails on Groovy - Clear and Flush Current Hibernate Session Data and Evict All Query Cache Data | Clearing Hibernate Query Cache in Grails
Hibernate already has support for query cache. And we know that when we perform a big task there are huge number queries remain in our cache factory. And more important that in most cases we don't need this caches so as a result cache factory getting full with unusual cache data.
This could be a performance issue - so it's better we clear cache on our own responsibility after a big task completed. |
Below are the procedure to flush and clear current session (hibernate session) data so that cache factory have enough space for further execution. |
import org.hibernate.SessionFactory import grails.util.Holders private static SessionFactory _sessionFactory static Boolean flushAndClearCache() { try { sessionFactory.currentSession.flush() sessionFactory.currentSession.clear() sessionFactory.getCache().evictEntityRegions() sessionFactory.getCache().evictCollectionRegions() sessionFactory.getCache().evictDefaultQueryRegion() sessionFactory.getCache().evictQueryRegions() return true } catch (Throwable ex) { log.error(ex.ex) return false } } static <T> T getBean(Class<T> requiredType) { try { return Holders.applicationContext.getBean(requiredType) } catch (Throwable e) { return null } } static SessionFactory getSessionFactory() { _sessionFactory = _sessionFactory ?: (_sessionFactory = getBean(SessionFactory)) } |
Thursday, January 2, 2020
Request Mocking In Grails For Back-end/Background Threads | Mock Request With Session
Request Mocking In Grails For Back-end/Background Threads | Mock Request With Session
And use be like below:
package com.pkm.util import grails.gsp.PageRenderer import grails.util.Holders import org.codehaus.groovy.grails.web.servlet.mvc.GrailsHttpSession import org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequest import org.springframework.web.context.request.RequestContextHolder import javax.servlet.ServletContext import javax.servlet.http.HttpServletRequest import javax.servlet.http.HttpSession /** * Created by pritom on 16/08/2017. */ class HibernateRequestUtils { static GrailsWebRequest getRequest() { return RequestContextHolder.getRequestAttributes() } static HttpSession getSession() { return request?.session } static void setValueToSession(String key, def value) { session.putAt(key, value) } static def getValueFromSession(String key) { return session.getAt(key) } static boolean isBound() { HttpServletRequest.isBound() } static boolean hasSession() { session != null } static def mock(Closure closure = null) { return HttpServletRequest.mock(closure) } static { HttpServletRequest.metaClass.static.with { isBound = { RequestContextHolder.requestAttributes != null } mock = { closure = null -> HttpServletRequest _request = PageRenderer.PageRenderRequestCreator.createInstance("/page/dummy") _request.IS_DUMMY = true _request."javax.servlet.include.servlet_path" = "/page/dummy.dispatch" GrailsWebRequest webRequest = new GrailsWebRequest( _request, PageRenderer.PageRenderResponseCreator.createInstance(new PrintWriter(new StringWriter())), Holders.servletContext ) { private MockedHttpSession _session MockedHttpSession getSession() { if (this._session == null) { this._session = new MockedHttpSession() } return this._session } } RequestContextHolder.setRequestAttributes(webRequest) if (closure) { def returned = closure() RequestContextHolder.resetRequestAttributes() return returned } return webRequest } } } } class MockedHttpSession extends GrailsHttpSession { MockedHttpSession() { super(null) } private LinkedHashMap attributes = [:] Object getAttribute(String name) { attributes[name] } Enumeration getAttributeNames() { Collections.enumeration(attributes.keySet()) } long getCreationTime() { 0 } long getLastAccessedTime() { 0 } int getMaxInactiveInterval() { 0 } ServletContext getServletContext() { return Holders.servletContext } @Deprecated String[] getValueNames() { [] as String[] } @Deprecated void putValue(String name, Object value) {} @Deprecated void removeValue(String name) {} void invalidate() {} boolean isNew() {true} void removeAttribute(String name) { attributes.remove(name) } void setAttribute(String name, Object value) { attributes[name] = value } void setMaxInactiveInterval(int arg0) {} }
And use be like below:
if (HibernateRequestUtils.isBound()) { DO YOU CODE IN HTTP REQUEST } else { HibernateRequestUtils.mock { DO YOUR CODE IN MOCK REQUEST AS YOU DO IN REAL REQUEST } }
Subscribe to:
Posts (Atom)