Friday, May 15, 2015

Spring Boot Internationalization with Default Locale for Message Strings

How to add Spring Boot Internationalization with Default Locale for Storing Message Strings such as Validation Messages in a message.properties file 


 This article will show you how to use a properties file to define static text in your application such as for validation message.

All the code is appended at the bottom of the article. 


Add Default locale and Message Source beans to your Application class 



 Add these classes to set your default locale and configure the location of your message properties file

 
Add beans to your Spring Boot Application class
Add locale and MessageSource beans to your Application Class


Add a Service and Interface to retrieve message text 


 This service will pull the default locale from the session and then get the message text from your properties file using the messageSource.

Create Service to get messages by locale
Add a service to get the msgs in your props file


In your controller, use the Message service to get the message text 


 You will inject the message service in the controller and then pass in the id to get the value from the props file


Inject svc and get message from i18n props file
Inject service into your controller and get the message



Create the message.properties file in the locale folder 


 In resources, create the locale folder and then create a file called messages_en_US.properties

Create localized message props file
Create message properties file



Review the coode here


You can view all the code here:

Thursday, May 7, 2015

Change Port on a Spring Boot Application when using intelliJ

Change Port on a Spring Boot Application when using intelliJ 



Two ways to change the port that the embedded Tomcat is using in a Spring Boot Application.

The first way is to modify the application properties in the resources folder:

Update application properties to change port
Update application props in Spring Boot Application



There are a couple issues with this approach.  You might only want this port change in your local environment and if you check it in by accident you might break things.


Alternatively, you can use a command line parameter.

Go to Run -> Edit Configurations -> VM options

Then enter in the following argument:

-Dserver.port=8090


Then click apply and OK and attempt to run the application again.

Update port on Spring Boot application using VM option
Update port using VM option



Tuesday, April 7, 2015

Convert Multiple Tasks to Sub-Tasks in JIRA similar to Bulk Update using Script Runner


How to Convert A Large Number of JIRA Tasks into Sub-Tasks using the Adaptavist Script Runner Plugin with JIRA



In JIRA, there is no way to convert Tasks into Sub-Tasks using the built-in Bulk Update functionality.  The lack of the feature is described in many JIRA tickets and Confluence posts on the official Atlassian site such as the two listed below:



There are many potential workarounds to this such as using selenium scripting to automate the conversion process using browser automation.  The best solution I have found is to use scripting within JIRA.





Backup your System




Before you attempt this, you should backup your JIRA instance because you potentially can make changes to tasks you did not intend.

Go to System settings and scroll down to the IMPORT & EXPORT section:

Use JIRA Backup functionality
Backup your JIRA instance




Install JIRA Adaptavist Scriptrunner




Download Adaptavist Scriptrunner

Get Adaptavist Scriptrunner:

https://marketplace.atlassian.com/plugins/com.onresolve.jira.groovy.groovyrunner


The file will be named something like this: groovyrunner-3.0.6.jar...

Upload and Install Scriptrunner
Upload your downloaded JIRA plugin as a JAR File
Upload your downloaded JIRA plugin as a JAR File






Open up Scriptrunner and run the script




Here is the script you want to run. This version uses a custom JQL query to find a comma delimited list of items that have certain values in a custom Functional Requirement field. It then loops through the list of issues and converts them to a subtasks then links the task to the parent task.
 
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.search.SearchProvider
import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.security.Permissions
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.user.ApplicationUser;
import com.atlassian.jira.issue.UpdateIssueRequest;


//Examples, 8 is my subtask issue type id. Will be different for others
//changeToSubTaskAndLink("AXDIS-509", "AXDIS-1045", "8")
//changeToSubTaskAndLink("AXDIS-509", "AXDIS-1046", "8")

def jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser.class)
def searchProvider = ComponentAccessor.getComponent(SearchProvider.class)
def issueManager = ComponentAccessor.getIssueManager()
def user = ComponentAccessor.getJiraAuthenticationContext().getUser()

//Add first function req here
//issueKey = 'AR-1231' for searching by id
def queryParamsString = "'Functional Requirement Id' ~ 5.3 " 

//Add all functional reqs after the first here
def functionalReqs = ['5.4', '5.5', '5.6', '5.7', '5.8', '5.9', '5.10', '5.11', '5.12']

functionalReqs.eachWithIndex { a, i ->
  queryParamsString += " OR 'Functional Requirement Id' ~ " + a
  
}

def parentIdKey = "AR-2125"
def subTaskIssueTypeId = "5"

def query = jqlQueryParser.parseQuery("project = AR AND affectedVersion = "Phase 2" AND 'Business Requirement Id' ~ '5' AND (" + queryParamsString + ")")
def results = searchProvider.search(query, user, PagerFilter.getUnlimitedFilter())
 
results.getIssues().each {documentIssue ->
    //log.debug(documentIssue.key)
    // if you need a mutable issue you can do:
    def issue = issueManager.getIssueObject(documentIssue.id)
    // do something to the issue...
    //changeToSubTaskAndLink("AR-2125", "AR-1977", "5")
    changeToSubTaskAndLink(parentIdKey, documentIssue.key, subTaskIssueTypeId)
}

//Method to do all the work
def changeToSubTaskAndLink(parentId, childId, subTaskIssueTypeId)
{  //Get the parent Issue 
    def parent = ComponentManager.getInstance().getIssueManager().getIssueObject(parentId) 
 //Get the child Issue 
    MutableIssue child = (MutableIssue)ComponentManager.getInstance().getIssueManager().getIssueObject(childId) 
    //Change the child to the subtask type 
    child.setIssueTypeId(subTaskIssueTypeId) 
    
    
    
    //Update the issue 
    //ComponentManager.getInstance().getIssueManager().updateIssue() 
    ComponentAccessor.getIssueManager().updateIssue((ApplicationUser)ComponentManager.getInstance().jiraAuthenticationContext?.user, (MutableIssue)child, UpdateIssueRequest.builder().build())

    //Create the subtask link, if this is not done you'll end up with orphans 
    //ComponentManager.getInstance().getSubTaskManager().createSubTaskIssueLink(parent, child, ComponentManager.getInstance().jiraAuthenticationContext?.user) 
    ComponentAccessor.getSubTaskManager().createSubTaskIssueLink(parent, child, ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()) 
}

Wednesday, April 1, 2015

Tired Engineers: Welcome to the Future of Coffee Automation

Welcome to the Future of Coffee Automation


Introducing Brew().  A Coffee Automation system to initiate coffee brewing whenever your code quality starts to slip.

Brew detects when you start writing crappy code, brews you some coffee, and empowers you to PUT DOWN THE KEYBOARD AND PICK UP THE MUG!

The future of productivity for Software Engineers
The future of productivity for Software Engineers

Brew() will save your life and the lives of your team.  Engineers depend on it.


So what are you waiting for!?!?!

Learn more about brew here:  Brew()


Monday, February 2, 2015

Add Stormpath User Mgmt Dependencies to Grails

Add Stormpath User Mgmt Dependencies to Grails


How to add dependencies for Stormpath to your grails application.


In your BuildConfig.groovy in the dependencies section you need to add 3 dependencies.

These artifacts are up to date as of 2/2/2015 so you may need to look up the newest version here:  http://docs.stormpath.com/java/quickstart/


Here are the dependencies you need to add.

BuildConfig.groovy
 
dependencies {


        //Stormpath user mgmt
        compile 'com.stormpath.sdk:stormpath-sdk-api:1.0.RC3.1'
        runtime 'com.stormpath.sdk:stormpath-sdk-httpclient:1.0.RC3.1'
        runtime 'com.stormpath.sdk:stormpath-sdk-oauth:1.0.RC3.1'
    }


Here are the original Maven imports in XML format for reference:

<dependency>
    <groupId>com.stormpath.sdk</groupId>
    <artifactId>stormpath-sdk-api</artifactId>
    <version>1.0.RC3.1</version>
</dependency>
<dependency>
    <groupId>com.stormpath.sdk</groupId>
    <artifactId>stormpath-sdk-httpclient</artifactId>
    <version>1.0.RC3.1</version>
    <scope>runtime</scope>
</dependency>
<!-- This next runtime dependency is only necessary if you have
     a REST API and you want to secure it with OAuth: -->
<dependency>
    <groupId>com.stormpath.sdk</groupId>
    <artifactId>stormpath-sdk-oauth</artifactId>
    <version>1.0.RC3.1</version>
    <scope>runtime</scope>
</dependency>



Stormpath allows you to rely on their secure infrastructure so that you can focus on writing your application code:
https://stormpath.com/

I use Stormpath as a plugin with Heroku
http://heroku.com/

Friday, October 31, 2014

Use Chrome for Development and Allow Cross-domain Javascript and AJAX


Use Another Instance of Chrome while Retrieving Content or Data from an Ajax Source on a Different Domain



If you are developing an application and calling a data source from another domain, you may encounter trouble when trying to use AJAX to retrieve a JSON data source from a service API for instance.


You may see an error message like the following:


Chrome

XMLHttpRequest cannot load [THE_URL_ENDPOINT].  No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.

- OR -

IE

SEC7118: XMLHttpRequest for [THE_URL_ENDPOINT] required Cross Origin Resource Sharing (CORS). 

SEC7119: XMLHttpRequest for [THE_URL_ENDPOINT] required CORS preflight. 

SEC7120: Origin http://localhost:8080 not found in Access-Control-Allow-Origin header. 

SCRIPT7002: XMLHttpRequest: Network Error 0x80070005, Access is denied.




There are many solutions to this such as using JSONP or modifying the header, Access-Control-Allow-Origin, on the responding service.  If none of these options are feasible for you you can run Chrome with cross-domain AJAX calls enabled.

You will want to run a seperate instance of chrome with web security disabled so that you can still use your own version of Chrome for personal use.

Run Separate Instance of Chrome with Disabled Web Security to Execute AJAX Calls from Different Domains





There is a flag in:  chrome://flags/ that allows you to disable web security.


You can run chrome with this flag using the following command assuming a standard Chrome Install.

"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --user-data-dir="C:/Chrome dev session2" --disable-web-security


Example:

Run Chrome with web security disabled for cross-domain requests
Run Chrome with --disable-web-security flag enabled 


After running this command, a new folder should be created on your C:/ drive.  This folder will contain user settings unique to this chrome instance.

Therefore, you will be able to run your own instance of Chrome for secure web browsing and then this instance of Chrome for development.  All the settings in this version of Chrome will be independent from you primary Chrome Instance.


A new instance of chrome will open up with a warning message indicating web security is disabled and the --disable-web-security flag is being used.  You can set a new home page on the browser instance to the local URL of your page in development.

Independent instance of Chrome for Cross-domain Javascript/AJAX
New Instance of Chrome for testing Cross Domain AJAX Calls

You can have your normal personal instance of chrome running and then run this command whenever you need to test a web application that needs to access a cross-domain data source.


Monday, October 13, 2014

Disabled Save Button on Forms while Saving in Salesforce



How to Disable the Save Button on your Form while the Form is Saving to Prevent Multiple Submissions in a Custom Salesforce Visualforce Page



Salesforce default functionality on forms will disable the save button after the form is submitted to prevent multiple submissions.

The disabled Save button will look like:

Disabled save button after submitting a form in Salesforce
Disabled save button after form submit

When creating your own VisualForce page you can write custom code to mimic this functionality in your forms using just Javascript and modifying the button's CSS styles.





Create Javascript functions to disable and enable the save button




You will need to create 2 Javascript functions that will enable and disable the button by modifying the css and properties of the save button.

I am using jQuery but you can also do this with vanilla Javascript. I am currently using a unique style class attached to the button to look it up for convenience since this page does not get modified very often if ever and also because the element id is used by Salesforce for internal SFDC functionality.

    function disableSave() {
     j$(".saveButtonId").prop("disabled","true");
        j$(".saveButtonId").val("Saving...");
                
        j$(".saveButtonId").css( "border-color", "#c4c4c4" );
        j$(".saveButtonId").css( "color", "#909090" );
    }

    function enableSave() {
        j$(".saveButtonId").removeProp( "disabled" )
        j$(".saveButtonId").val("Save");
            
        j$(".saveButtonId").css( "border-color", "#7f7f7f" );
        j$(".saveButtonId").css( "color", "#333" ); 
    }    


Add events to the Salesforce save button on your Visualforce Page




You will then need to bind your Javascript functions to the onclick and oncomplete event on your save button. I am using binding within the tag since I am using a custom apex:commandbutton Visualforce tag to create the save button.

This will disable the save button on click and re-enable the button when the AJAX request completes that clicking your save button initiated.

<apex:commandbutton action="{!save}" onclick="disableSave()" oncomplete="enableSave()" status="savingStatus" styleclass="saveButtonId" value="Save"> 
</apex:commandbutton>