Since Groovy 1.7.9 we can use the collectEntries method for a Collection to get a Map. We use a closure to transform the elements in the collection to a map entry. And the end result is a Map with all the map entries. |
List<String> words = ["Grails", "On", "Groovy"] Map map = words.collectEntries { [ (it): it.contains("G") ] } println(map) |
Which will output as below: |
[Grails:true, On:false, Groovy:true] |
Sunday, June 17, 2018
Grails on Groovy > Transform Collection / List to a Map with collectEntries > Get Map From Array List > Convert List To Corresponding Map Entity
Grails on Groovy > Transactions > Transaction Block > Read Only Transactions > With New Transaction > Transactions With Read Only Stage
We all know that Grails services are transactional by default. When you create a service you see that there is a annotation @Transactional exists over class name. Transactional means all transactions will persist on database or no one will persist.
We can set transactions read only mode if we wish in a transactional block if we need. Below is a code snippet: |
package com.pkm import grails.transaction.Transactional import org.springframework.transaction.TransactionStatus @Transactional class HomeService { TransactionStatus transactionStatus void callMe() { Table1 table1 = Table1.last() new Table2(table1: table1, subject: "S3", score: 3D).save() transactionStatus.setRollbackOnly() Table2.withNewTransaction { TransactionStatus tx -> table1 = Table1.last() new Table2(table1: table1, subject: "S4", score: 3D).save() tx.setRollbackOnly() } } } |
In above code block, we inject a bean named transactionStatus which actually maintain if a service definition is read only or not. We can set it to read only mode using transactionStatus.setRollbackOnly(). We can do the same job for when we do anything in withNewTransaction block. You can see there is another transactionStatus occur for that new region. So you can also set it to read only mode. |
Grails on Groovy > Create Criteria > Create Alias > Grails Create Alias > Create Alias With Additional Criteria
We frequently use createAlias to create alias between entity. It actually create connection based on foreign key and primary key between two entities. Below is a example how we create alias between entities: |
Table1.createCriteria().list { createAlias("scores", "scores") } |
Which will produce SQL like below where we can see that foreign key of table1 create a link with table2_child based on primary key id as following: |
select ... from table1 this_ inner join table2_child scores1_ on (this_.id=scores1_.table1_id) |
But if we need more on add to filter when joining them, yeah, we can do that. We can add extra conditions to on part of that SQL. To do so, first need to create a groovy file like below: |
package com.pkm import org.hibernate.Criteria import org.hibernate.HibernateException import org.hibernate.criterion.CriteriaQuery import org.hibernate.criterion.Criterion import org.hibernate.engine.spi.TypedValue class CustomSqlJoin implements Criterion { private Double score = null; CustomSqlJoin(Double score) { this.score = score } //Use Example > createAlias("scores", "scores", JoinType.INNER_JOIN, new CustomSqlJoin(2D)) @Override String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { String alias = criteriaQuery.getSQLAlias(criteria) return "${alias}.score > ${this.score}" } @Override TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { return new TypedValue[0] } } |
And you can use the above custom condition using as below example: |
Table1.createCriteria().list { createAlias("scores", "scores", JoinType.INNER_JOIN, new CustomSqlJoin(2D)) "ne" "id", System.currentTimeMillis() } |
Which will generate below SQL |
select ... from table1 this_ inner join table2_child scores1_ on this_.id=scores1_.table1_id and ( scores1_.score > 2.0 ) where this_.id<>? |
Saturday, June 16, 2018
How to handle HTTP 403 forbidden error in Java
Sometimes when trying to connect to a web service using a java client, we may face a 403 forbidden HTTP response code, it is workable but in some reason the service is accessible normally from web browsers. |
The HTTP 403 forbidden error doesn’t necessarily occur due to missing authentication attributes or invalid authentication, some web services would only authorize web browsers or some specific clients to access them, while they deny any requests coming from third-party clients. And we are going to handle this situation. |
This problem is normally resolved by imitating the web browser request so that the web service deals with the java client as if it was a web browser. |
Below is a typical request logged from a browser: |
GET /feeds HTTP/1.1 Host: publicservice.com:443 Accept: */* Accept-Encoding: gzip, deflate, br Accept-Language: en-US,en;q=0.9 Cookie: OGP=-4061129:; SID=FAYIU7tO.... Referer: https://clients5.google.com/pagead/drt/dn/ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36 X-Client-Data: CIa2yQEIpLbJAQjBtskBCKmdygEIqKPKARiSo8oB |
As noticed, the “User-Agent” header specifies the name and the type of the client which is trying to access the service, so in order to imitate the web browser we need to add this header to our request. Following is how to add it using HttpUrlConnection: |
String url = "https://xxx.com/yyy"; URL obj = new URL(url); HttpsURLConnection con = (HttpsURLConnection) obj.openConnection(); con.setRequestMethod("GET"); con.setRequestProperty("Content-Type", "application/json"); con.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"); |
Grails on Groovy > Bind Metamethod of Hibernate Criteria Builder > Create Custom Function / Custom Method Under HibernateCriteriaBuilder > HibernateCriteriaBuilder Meta Method
To bind custom method with hibernate criteria builder you first need to create a groovy file named HibernateCriteriaListener like below: |
package com.pkm import grails.util.Holders import org.codehaus.groovy.grails.commons.GrailsApplication import org.grails.datastore.mapping.core.Datastore import org.grails.datastore.mapping.engine.event.* import org.springframework.context.ApplicationEvent import grails.orm.HibernateCriteriaBuilder class HibernateCriteriaListener extends AbstractPersistenceEventListener { protected HibernateCriteriaListener(Datastore datastore) { super(datastore) HibernateCriteriaBuilder.metaClass.myMethod = { info, value = null -> println("NAME=${info} VALUE=${value}") } } @Override protected void onPersistenceEvent(AbstractPersistenceEvent event) { } @Override boolean supportsEventType(Class<? extends ApplicationEvent> aClass) { return false } static void initialize(GrailsApplication application) { application.mainContext.eventTriggeringInterceptor.datastores.each { k, datastore -> Holders.applicationContext.addApplicationListener(new HibernateCriteriaListener(datastore)) } } } |
Now we need to register the above functionality from BootStrap, so you need to do following: |
import com.pkm.HibernateCriteriaListener import org.codehaus.groovy.grails.commons.GrailsApplication import org.codehaus.groovy.grails.web.servlet.GrailsApplicationAttributes import org.hibernate.dialect.function.SQLFunctionTemplate import org.springframework.context.ApplicationContext class BootStrap { def init = { servletContext -> ApplicationContext applicationContext = servletContext.getAttribute(GrailsApplicationAttributes.APPLICATION_CONTEXT) GrailsApplication application = (GrailsApplication) applicationContext.getBean("grailsApplication") /* REGISTER HIBERNATE EVENT LISTENER */ HibernateCriteriaListener.initialize(application) } def destroy = { } } |
And finally you can use custom criteria method using below sample: |
Table1.createCriteria().list { delegate.myMethod("name", "value") } |
jQuery UI Dialog > Disable Auto Focus > Prevent jQuery UI Dialog From Setting Focus To First Textbox > Disable Auto Focus Of First Input Box > Prevent Auto Scroll To Top Of Dialog Box
There are several problems related to auto focus of jQuery UI Dialog. Some of them are below: > Opening jQuery Date picker automatically on focus of dialog, because of first element get auto focused. > If dialog has scrollbar visible, its auto scrolled to top to auto focus first element of dialog. |
So to disable auto focus input element inside UI dialog, add the following code before you call dialog. This will clear out the autofocus code. |
$.ui.dialog.prototype._focusTabbable = function(){}; |
BEGENING OF CSS > TABLE WITH SCROLLBAR AND FIXED HEADER POSITION > How to make Scrollable Table with fixed headers using CSS
|
Jsfiddle link to check |
<div class="fixed-table-container"> <div class="header-background"> </div> <div class="fixed-table-container-inner"> <table cellspacing="0"> <thead> <tr> <th class="first"> <div class="th-inner">First</div> </th> <th> <div class="th-inner">Second</div> </th> <th> <div class="th-inner">Third</div> </th> <th> <div class="th-inner">Fourth</div> </th> </tr> </thead> <tbody> <tr> <td>First</td> <td>First</td> <td>First</td> <td>First</td> </tr> <tr> <td>First</td> <td>Second</td> <td>Third</td> <td>Fourth</td> </tr> <tr> <td>First</td> <td>Second</td> <td>Third</td> <td>Fourth</td> </tr> <tr> <td>First</td> <td>Second</td> <td>Third</td> <td>Fourth</td> </tr> <tr> <td>First</td> <td>Second</td> <td>Third</td> <td>Fourth</td> </tr> <tr> <td>First</td> <td>Second</td> <td>Third</td> <td>Fourth</td> </tr> <tr> <td>First</td> <td>Second</td> <td>Third</td> <td>Fourth</td> </tr> <tr> <td>First</td> <td>Second</td> <td>Third</td> <td>Fourth</td> </tr> <tr> <td>First</td> <td>Second</td> <td>Third</td> <td>Fourth</td> </tr> <tr> <td>First</td> <td>Second</td> <td>Third</td> <td>Fourth</td> </tr> <tr> <td>First</td> <td>Second</td> <td>Third</td> <td>Fourth</td> </tr> <tr> <td>First</td> <td>Second</td> <td>Third</td> <td>Fourth</td> </tr> <tr> <td>First</td> <td>Second</td> <td>Third</td> <td>Fourth</td> </tr> <tr> <td>First</td> <td>Second</td> <td>Fourth</td> <td>Third</td> </tr> <tr> <td>Last</td> <td>Last</td> <td>Last</td> <td>Last</td> </tr> </tbody> </table> </div> </div> |
.fixed-table-container { width: 70%; height: 200px; border: 1px solid black; margin: 10px auto; background-color: white; position: relative; padding-top: 30px; } .fixed-table-container .header-background { background-color: #D5ECFF; height: 30px; position: absolute; top: 0; right: 0; left: 0; border-bottom: 1px solid black; } .fixed-table-container .fixed-table-container-inner { overflow-x: hidden; overflow-y: auto; height: 100%; } .fixed-table-container table { background-color: white; width: 100%; overflow-x: hidden; overflow-y: auto; } .fixed-table-container th { padding: 0 5px; text-align: left; } .fixed-table-container .first .th-inner { border-left: none; padding-left: 6px; } .fixed-table-container .th-inner { position: absolute; top: 0; line-height: 30px; text-align: left; border-left: 1px solid black; padding-left: 5px; margin-left: -5px; } .fixed-table-container td + td { border-left: 1px solid #ccc; } .fixed-table-container td { border-bottom: 1px solid #ccc; padding: 5px; text-align: left; } |
Subscribe to:
Posts (Atom)