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. |
Sunday, June 17, 2018
Grails on Groovy > Transactions > Transaction Block > Read Only Transactions > With New Transaction > Transactions With Read Only Stage
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; } |
Grails on Groovy > Changing default id name and type from an entity > Custom ID field > Custom ID field value generate algorithm
While developing a simple application at work I need to specify id field to some other field suppose named 'my_id' and want to use assigned value instead of using default auto_generated. |
I have a table with a column named my_id of type varchar. But GORM by default auto generate an id property with the long type. The solution is straight forward, just call the method id in the mapping closure, with the following param(s): |
package com.pkm class Foo { String my_id static constraints = {} static mapping = { id generator: 'assigned', name: 'my_id' } } |
The generator is the strategy to auto-generate the id, you can use a sequence or something like, since it’s a string the value will be assigned, not generated. The name is the current property to bind the value (my_id in this case). |
We can use our custom class to generate id of entity. For to do this, we need to define a class like below: |
package com.pkm import org.hibernate.HibernateException import org.hibernate.engine.spi.SessionImplementor import org.hibernate.id.IdentifierGenerator class IdGenerator implements IdentifierGenerator { static Map id = [:] @Override Serializable generate(SessionImplementor session, Object o) throws HibernateException { String name = o.class.simpleName if (!id[name]) { id[name] = Table1.executeQuery("select max(id) from ${name}") if (id[name]) id[name] = id[name][0] else id[name] = 0 } return (++id[name]) } } |
And we need to define our class like below: |
package com.pkm class Table1 { Long id String name String roll static mapping = { table("table1") id generator: "com.pkm.IdGenerator", column:"id", unique:"true" } } |
If you want to globally use same configuration then you have to modify Config.groovy, you have to add below entity to Config.groovy |
grails.gorm.default.mapping = { version false id generator:"com.pkm.IdGenerator", column:"id", unique:"true" } |
And finally you can browse for more information |
All generators implement the interface org.hibernate.id.IdentifierGenerator. This is a very simple interface. Some applications can choose to provide their own specialized implementations, however, Hibernate provides a range of built-in implementations. The shortcut names for the built-in generators are as follows: increment generates identifiers of type long, short or int that are unique only when no other process is inserting data into the same table. Do not use in a cluster. identity supports identity columns in DB2, MySQL, MS SQL Server, Sybase and HypersonicSQL. The returned identifier is of type long, short or int. sequence uses a sequence in DB2, PostgreSQL, Oracle, SAP DB, McKoi or a generator in Interbase. The returned identifier is of type long, short or int hilo uses a hi/lo algorithm to efficiently generate identifiers of type long, short or int, given a table and column (by default hibernate_unique_key and next_hi respectively) as a source of hi values. The hi/lo algorithm generates identifiers that are unique only for a particular database. seqhilo uses a hi/lo algorithm to efficiently generate identifiers of type long, short or int, given a named database sequence. uuid uses a 128-bit UUID algorithm to generate identifiers of type string that are unique within a network (the IP address is used). The UUID is encoded as a string of 32 hexadecimal digits in length. guid uses a database-generated GUID string on MS SQL Server and MySQL. native selects identity, sequence or hilo depending upon the capabilities of the underlying database. assigned lets the application assign an identifier to the object before save() is called. This is the default strategy if no element is specified. select retrieves a primary key, assigned by a database trigger, by selecting the row by some unique key and retrieving the primary key value. foreign uses the identifier of another associated object. It is usually used in conjunction with a primary key association. sequence-identity a specialized sequence generation strategy that utilizes a database sequence for the actual value generation, but combines this with JDBC3 getGeneratedKeys to return the generated identifier value as part of the insert statement execution. This strategy is only supported on Oracle 10g drivers targeted for JDK 1.4. Comments on these insert statements are disabled due to a bug in the Oracle drivers. |
Subscribe to:
Posts (Atom)