Tuesday, October 17, 2017

Grails How to change logging level in runtime | Grails Set Log Level for Grails

Grails How to change logging level in runtime | Grails Set Log Level for Grails

Need to create a util class at first as below:


package com.log4j

import grails.util.Holders
import org.apache.log4j.Category
import org.apache.log4j.Level
import org.apache.log4j.Logger

/**
 * Created by pritom on 17/10/2017.
 */
class UtilsBase {
    protected static Logger log

    static void setLogLevel() {
        Level level = Holders.config?.myconfig?.log4j?.logLevel ?: Level.ERROR
        println("SETTING-LOG-LEVEL=${level}")
        Enumeration allLoggers = log.getLoggerRepository().getCurrentCategories()
        log.setLevel(level)
        while (allLoggers.hasMoreElements()) {
            Category category = (Category) allLoggers.nextElement()
            category.setLevel(level)
        }
    }

    static {
        println("Log-enabled-for-${this.class.simpleName}")
        log = Logger.getLogger(this.class)
    }
}

Need to do something in Config.groovy as below:


myconfig {
    log4j {
        /* Here you can define your LOG level */
        logLevel = Level.INFO
    }
}

// log4j configuration
// log4j configuration
log4j.main = {
    def pattern = new PatternLayout("%d{yyyy-MM-dd//HH:mm:ss.SSS} [%t] %x %-5p %c{2} - %m%n")

    appenders {
        console name: "stdout", layout: pattern
    }

    error   'org.codehaus.groovy.grails.web.servlet',        // controllers
            'org.codehaus.groovy.grails.web.pages',          // GSP
            'org.codehaus.groovy.grails.web.sitemesh',       // layouts
            'org.codehaus.groovy.grails.web.mapping.filter', // URL mapping
            'org.codehaus.groovy.grails.web.mapping',        // URL mapping
            'org.codehaus.groovy.grails.commons',            // core / classloading
            'org.codehaus.groovy.grails.plugins',            // plugins
            'org.codehaus.groovy.grails.orm.hibernate',      // hibernate integration
            'org.springframework',
            'org.hibernate',
            'net.sf.ehcache.hibernate',
            'com.log4j'

    debug   'com.log4j'

    warn    'org.springframework',
            'org.hibernate',
            'grails.plugins.springsecurity',
            'groovyx.net.http',
            'com.log4j'

    all     'grails.app'
}


Now you have to set log level fro BootStrap.goovy as below


import com.log4j.UtilsBase

class BootStrap {

    def init = { servletContext ->
        UtilsBase.setLogLevel()
    }
    def destroy = {

    }
}


And finally start loggin


package com.log4j

class Log4jController extends UtilsBase {
    def index() {
        log.info("Info")
        log.warn("Warn")
        log.error("Error")
        render ""
    }
}

Will output as below:


2017-10-17//16:16:15.512 [http-bio-8808-exec-4]  INFO  log4j.Log4jController - Info
2017-10-17//16:16:15.515 [http-bio-8808-exec-4]  WARN  log4j.Log4jController - Warn
2017-10-17//16:16:15.515 [http-bio-8808-exec-4]  ERROR log4j.Log4jController - Error




Monday, October 16, 2017

Grails 2.4 Traditional WebSocket Example | Grails Chat Application | Traditional Web Socket Chat Example

Grails 2.4 Traditional WebSocket Example | Grails Chat Application | Traditional Web Socket Chat Example

At first you need to create a configurator class under src/groovy as below:


import javax.websocket.HandshakeResponse
import javax.websocket.server.HandshakeRequest
import javax.websocket.server.ServerEndpointConfig
/**
 * Created by pritom on 5/10/2017.
 */
class TraditionalWebSocketConfigurator extends ServerEndpointConfig.Configurator {
    @Override
    public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {
        config.userProperties.put("MyKey", 100)
        config.userProperties.put("session", request.httpSession)
    }
}

Next you have to create a Handler class under scr/groovy as below:


import org.springframework.scheduling.TaskScheduler
import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler

import javax.servlet.ServletContext
import javax.servlet.annotation.WebListener
import javax.websocket.*
import javax.websocket.server.ServerContainer
import javax.websocket.server.ServerEndpoint
/**
 * Created by pritom on 5/10/2017.
 */
@WebListener
@ServerEndpoint(value = "/WebSocket/traditional", configurator = TraditionalWebSocketConfigurator.class)
class TraditionalWebSocketHandler {
    private static List<Session> clients = []
    private static TaskScheduler clientRemoveScheduler = new ConcurrentTaskScheduler()

    @OnOpen
    public void handleOpen(Session userSession, EndpointConfig endpointConfig) {
        clients.add(userSession)
        println "WE HAVE OPEN SESSION #${userSession.id} " +
                "SESSION ${userSession.userProperties.session.id}"
    }

    @OnMessage
    public void handleMessage(String message, Session userSession) throws IOException {
        if (message) {
            println("SENDING TO ${clients.findAll { it.isOpen() }.size()}/${clients.size()} CLIENTS")
            message = "${userSession.id}: ${message}".toString()
            clients.findAll { it.isOpen() }.each { it.basicRemote.sendText(message) }
        }
    }

    @OnClose
    public void handeClose(Session userSession) throws SocketException {
        println "ONE CONNECTION CLOSED"
    }

    @OnError
    public void handleError(Throwable throwable) {
        println("HANDLE ERROR")
        throwable.printStackTrace()
    }

    static void init(final ServletContext servletContext) {
        final ServerContainer serverContainer = servletContext.getAttribute("javax.websocket.server.ServerContainer")
        serverContainer.addEndpoint(TraditionalWebSocketHandler)
        serverContainer.defaultMaxSessionIdleTimeout = 0

        clientRemoveScheduler.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    clients.removeAll { !it.isOpen() }
                }
                catch (Exception ex) {

                }
            }
        }, 1000L * 10)
    }
}

Next step is to init Handler from BootStrap.groovy as below:


import com.socket.TraditionalWebSocketHandler
import org.codehaus.groovy.grails.commons.GrailsApplication

import javax.servlet.ServletContext

class BootStrap {
    ServletContext servletContext
    GrailsApplication grailsApplication

    def init = { servletContext ->
        TraditionalWebSocketHandler.init(servletContext)
    }

    def destroy = {

    }
}

You are already done, next step is to generate a view to show chat window:


class SocketController {
    def index() {
        session.name = "Pritom Kumar"
        render view: "index"
    }
}


<html>
<head>
    <asset:javascript src="jquery-2.1.3.js"/>
</head>

<body>

<table>
    <tr>
        <td>User Message</td>
        <td><input type="text" autofocus class="message" required/></td>
    </tr>
    <tr>
        <td></td>
        <td><input class="button" type="button" value="Send"/></td>
    </tr>
</table>

<div class="log_div"></div>

<script type="text/javascript">
    var socket = new WebSocket("ws://localhost:8807/socket-chat-application/WebSocket/traditional");
    socket.onopen = function () {
        socket.send('Hello');
    };
    socket.onmessage = function (message) {
        $(".log_div").prepend("<div>" + message.data + "</div>");
    };
    socket.onclose = function () {

    };
    socket.onerror = function () {

    };

    $(".button").click(function () {
        var value = $.trim($(".message").val());
        if (value.length > 0) {
            socket.send(value);
            $(".message").val("").focus();
        }
    });

    $(".message").keypress(function (e) {
        if (e.keyCode == 13) {
            $(".button").click();
        }
    });
</script>

</body>
</html>

And finally below is a screenshot of browser interaction:



Sunday, October 15, 2017

Grails - Register SessionListener as a Spring Bean

Grails - Register SessionListener as a Spring Bean

At first you have to create an listener of session as below:


package com.multidb.listener

import javax.servlet.http.HttpSessionEvent
import javax.servlet.http.HttpSessionListener
/**
 * Created by pritom on 15/10/2017.
 */
class HttpSessionServletListener implements HttpSessionListener {
    @Override
    void sessionCreated(HttpSessionEvent event) {
        println("HttpSessionServletListener:httpSessionCreated:${event.session}")
    }

    @Override
    void sessionDestroyed(HttpSessionEvent event) {
        println("HttpSessionServletListener:sessionDestroyed:${event.session}")
    }
}

Then you need to register in grails-app/conf/spring/resources.groovy as below:


import com.multidb.listener.HttpSessionServletListenererDataSource

beans = {
    httpSessionServletListener(HttpSessionServletListener) {

    }
}

And finally in Bootstrap.groovy


import com.multidb.listener.HttpSessionServletListener
import org.codehaus.groovy.grails.commons.GrailsApplication
import javax.servlet.ServletContext

class BootStrap {
    ServletContext servletContext
    GrailsApplication grailsApplication
    HttpSessionServletListener httpSessionServletListener

    def init = { servletContext ->
        servletContext.addListener(httpSessionServletListener)
    }

    def destroy = {

    }
}

So after an session is created or destroyed your custom listener will be notified.

Thursday, October 12, 2017

Grails Custom Projection | Projections Property | Custom Projection Property

Grails Custom Projection | Projections Property | Custom Projection Property

You have to create a groovy file as below:


import org.hibernate.Criteria
import org.hibernate.HibernateException
import org.hibernate.criterion.CriteriaQuery
import org.hibernate.criterion.SimpleProjection
import org.hibernate.dialect.function.SQLFunction
import org.hibernate.type.Type
/**
 * Created by pritom on 25/09/2017.
 */
class HomeChildCount extends SimpleProjection {
    protected final String propertyName
    private final String functionName

    HomeChildCount() {
        this("sum", "id")
    }

    HomeChildCount(String functionName, String propertyName) {
        this.functionName = functionName
        this.propertyName = propertyName
    }

    public String getFunctionName() {
        return this.functionName
    }

    public String getPropertyName() {
        return this.propertyName
    }

    public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
        Type type = this.getFunction(criteriaQuery).getReturnType(criteriaQuery.getType(criteria, this.getPropertyName()), criteriaQuery.getFactory())
        return [type] as Type[]
    }

    public String toSqlString(Criteria criteria, int loc, CriteriaQuery criteriaQuery) throws HibernateException {
        String functionFragment = this.getFunction(criteriaQuery).render(criteriaQuery.getType(criteria, this.getPropertyName()), this.buildFunctionParameterList(criteria, criteriaQuery), criteriaQuery.getFactory())
        //return functionFragment + " as y" + loc + '_'
        return "(select count(c.id) from child c where c.home_id=this_.id) as y" + loc + "_"
    }

    protected SQLFunction getFunction(CriteriaQuery criteriaQuery) {
        return this.getFunction(this.getFunctionName(), criteriaQuery)
    }

    protected SQLFunction getFunction(String functionName, CriteriaQuery criteriaQuery) {
        SQLFunction function = criteriaQuery.getFactory().getSqlFunctionRegistry().findSQLFunction(functionName)
        if(function == null) {
            throw new HibernateException("Unable to locate mapping for function named [" + functionName + "]")
        }
        else {
            return function
        }
    }

    protected List buildFunctionParameterList(Criteria criteria, CriteriaQuery criteriaQuery) {
        return this.buildFunctionParameterList(criteriaQuery.getColumn(criteria, this.getPropertyName()))
    }

    protected List buildFunctionParameterList(String column) {
        return Collections.singletonList(column)
    }

    public String toString() {
        return this.functionName + "(" + this.propertyName + ')'
    }
}

You have to attach this projection property as below:


Object.metaClass.with {
    activeChildCount = { String alias ->
        delegate.delegate.addProjectionToList(new HomeChildCount(), alias)
    }
}

And finally you can use the custom projection as below:


Home.createCriteria().list {
    resultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP)
    projections {
        groupProperty("id", "id")
        groupProperty("name", "name")
        groupProperty("roll", "roll")
        groupProperty("departmentName", "departmentName")
        activeChildCount("child_count")
    }
}

Grails Create Criteria | Grails CreateCriteria | Custom Criteria | Custom Criteria Condition

Grails Create Criteria | Grails CreateCriteria | Custom Criteria | Custom Criteria Condition

You have to create a groovy class as below:


import org.hibernate.Criteria
import org.hibernate.HibernateException
import org.hibernate.criterion.CriteriaQuery
import org.hibernate.criterion.Criterion
import org.hibernate.engine.spi.TypedValue
import org.hibernate.internal.util.StringHelper

/**
 * Created by pritom on 25/09/2017.
 */
class CustomCriteria implements Criterion {
    private static final TypedValue[] NO_VALUES = new TypedValue[0]
    private final String propertyName

    CustomCriteria(String propertyName) {
        this.propertyName = propertyName
    }

    public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
        String[] columns = criteriaQuery.findColumns(this.propertyName, criteria)
        String result = StringHelper.join(" or ", StringHelper.suffix(columns, " is not null"))
        if(columns.length > 1) {
            result = '(' + result + ')'
        }

        return result
    }

    public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
        return NO_VALUES
    }

    public String toString() {
        return this.propertyName + " is not null"
    }
}

Then you to attach those functions as below:


Object.metaClass.with {
    customCriteria = {
        String propertyName = delegate.delegate.calculatePropertyName(it)
        delegate.delegate.addToCriteria(new CustomCriteria(propertyName))
        return delegate.delegate
    }
}

Then you can use your custom criteria function as below:


return (List<Home>) Home.createCriteria().list {
    setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
    createAlias("childs", "childs")
    isNotNull("childs.id")
    customCriteria("childs.id")
    not { isNull("childs.id") }
}

Saturday, October 7, 2017

Java HttpsURLConnection and TLS 1.2 | Enable TLS 1.1 and 1.2 for Clients on Java 7 | Enabling TLSv1.2 with HttpsUrlConnection

You will have to create an SSLContext to set the Protocoll:

then you just have to set the SSLContext to the HttpsURLConnection:

httpsCon.setSSLSocketFactory(sc.getSocketFactory());


package com.pkm;

import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;

public class TLSRequest {
    public static void main(String[] args) throws Exception {
        HttpsURLConnection connection = (HttpsURLConnection) new URL("https://pritom.com").openConnection();
        // TLSv1 | TLSv1.1 | TLSv1.2
        SSLContext sc = SSLContext.getInstance("TLSv1");
        sc.init(null, null, new java.security.SecureRandom()); 
        connection.setSSLSocketFactory(sc.getSocketFactory());
    }
}

Stripe Payment API: Create Charge Or Payment Using Java Code

You need a Token (Saved credit card instance) to create a Payment which is known as Charge in Stripe API. Creating Charge in Stripe is equal to creating a Payment. 

Payment API documentation:
https://stripe.com/docs/api#charges 


package com.pkm;

import common.HttpJavaClient;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author PRITOM
 */
public class StripeCreatePayment {
    static final String API_KEY = "sk_test_eXF5nNyXat29WjWrqHK92rcj";
    static final String TOKEN_URL = "https://api.stripe.com/v1/tokens";
    static final String PAYMENT_URL = "https://api.stripe.com/v1/charges";
    
    public static void main(String[] args) {        
        Map params = new HashMap();
        params.put("amount", "210");
        params.put("currency", "aud");
        params.put("source", createToken());
        params.put("description", (new Date()).toString());
        String paramString = HttpJavaClient.buildParameters(params);
        
        Map headers = new HashMap();
        headers.put("Authorization", "Bearer " + API_KEY);
        headers.put("tls", "TLSv1.2");
        
        HttpJavaClient.Response response = HttpJavaClient.doPost(PAYMENT_URL, paramString, HttpJavaClient.Type.URL_ENCODED, headers);
        HttpJavaClient.println(response);
    }
    
    static String createToken() {
        Map params = new HashMap();
        params.put("card[name]", "Pritom Kumar");
        params.put("card[number]", "4242424242424242");
        params.put("card[exp_month]", "12");
        params.put("card[exp_year]", "19");
        params.put("card[cvc]", "123");
        String paramString = HttpJavaClient.buildParameters(params);
        
        Map headers = new HashMap();
        headers.put("Authorization", "Bearer " + API_KEY);
        headers.put("tls", "TLSv1.2");
        
        HttpJavaClient.Response response = HttpJavaClient.doPost(TOKEN_URL, paramString, HttpJavaClient.Type.URL_ENCODED, headers);
        if (response.getCode() == 200) {
            String token = response.getBody().substring(response.getBody().indexOf("\"id\": \"") + 7);
            return token.substring(0, token.indexOf("\""));
        }
        return null;
    }
}

And output would be for successful transaction line below:


  "id": "ch_1BACCFFIwfarG3vBdzS2A09q",
  "object": "charge",
  "amount": 210,
  "amount_refunded": 0,
  "application": null,
  "application_fee": null,
  "balance_transaction": "txn_1BACCFFIwfarG3vBWUtFsX4N",
  "captured": true,
  "created": 1507359243,
  "currency": "aud",
  "customer": null,
  "description": "Sat Oct 07 12:54:06 BDT 2017",
  "destination": null,
  "dispute": null,
  "failure_code": null,
  "failure_message": null,
  "fraud_details": {},
  "invoice": null,
  "livemode": false,
  "metadata": {},
  "on_behalf_of": null,
  "order": null,
  "outcome": {
    "network_status": "approved_by_network",
    "reason": null,
    "risk_level": "normal",
    "seller_message": "Payment complete.",
    "type": "authorized"
  },
  "paid": true,
  "receipt_email": null,
  "receipt_number": null,
  "refunded": false,
  "refunds": {
    "object": "list",
    "data": [],
    "has_more": false,
    "total_count": 0,
    "url": "/v1/charges/ch_1BACCFFIwfarG3vBdzS2A09q/refunds"
  },
  "review": null,
  "shipping": null,
  "source": {
    "id": "card_1BACCDFIwfarG3vBAnQYrCBR",
    "object": "card",
    "address_city": null,
    "address_country": null,
    "address_line1": null,
    "address_line1_check": null,
    "address_line2": null,
    "address_state": null,
    "address_zip": null,
    "address_zip_check": null,
    "brand": "Visa",
    "country": "US",
    "customer": null,
    "cvc_check": "pass",
    "dynamic_last4": null,
    "exp_month": 12,
    "exp_year": 2019,
    "fingerprint": "CjZNbbCtG5QSnuIS",
    "funding": "credit",
    "last4": "4242",
    "metadata": {},
    "name": "Pritom Kumar",
    "tokenization_method": null
  },
  "source_transfer": null,
  "statement_descriptor": null,
  "status": "succeeded",
  "transfer_group": null
}