Monday, February 25, 2019

1. Overview

In PCF, any service is consumed through PCF marketplace. To consume a service, we need to create a service instance which does the provisioning. By default, this instance can be used only for a particular Org/Space in which instance has been created. 
Let's take an example to understand it in detail. Let's suppose we do have a REST based service and it puts the message in RabbitMQ. So we will create a service instance using the below command:


 cf create-service <SERVICE> <PLAN> <SERVICE_INSTANCE>



 Let's assume, we are currently in Org -TeamA and Space- Products. So this instance will be visible only in Products space. Now, Let's suppose you have any development work going on in Space Consumers and an application needs to consume this RabbitMQ service. Before PCF 2.3 version, it was not possible as service instance is not sharable across Orgs/spaces. The only solution was to put both applications into one space. Let's see now how we can share the service instances across Orgs/Spaces.

You can watch this video to understand this feature or read through the blog below:



2. Enable Service Instance Sharing

  • Service instances can be shared into multiple spaces and across orgs.
  • Developers and administrators can share service instances between spaces in which they have the Space Developer role.
  • Developers who have a service instance shared with them can only bind and unbind apps to that service instance. They cannot update, rename, or delete it.
  • Developers who have a service instance shared with them can view the values of any configuration parameters that were used to provision or update the service instance.
1. To view if the Service Instance sharing flag is enabled, we need to run below command:

> cf feature-flags
features                                      state
user_org_creation                             disabled
private_domain_creation                       enabled
app_bits_upload                               enabled
app_scaling                                   enabled
route_creation                                enabled
service_instance_creation                     enabled
diego_docker                                  disabled
set_roles_by_username                         enabled
unset_roles_by_username                       enabled
task_creation                                 enabled
env_var_visibility                            enabled
space_scoped_private_broker_creation          enabled
space_developer_env_var_visibility            enabled
service_instance_sharing                      enabled
hide_marketplace_from_unauthenticated_users   disabled
It is showing enabled for me. However, if you see it disabled for some reason, you can run below command to enable it.
> cf enable-feature-flag service_instance_sharing

Please note that only Administrator role has the access to enable feature flag. So contact your administrator if you are not an admin.

2. Next, we need to ensure the service which you want to allow for sharing has its broker enabled the sharing. Service broker must explicitly enable service instance sharing by setting a flag in their service-level metadata object. This allows service instances, of any service plan, to be shared across orgs and spaces. The "shareable" flag must be set to true in the service-level metadata to enable service instance sharing. If the flag is set to false or is absent, sharing is disabled:

{
   "services":[{
      "id":"521db166-a310-4b12-asdf-d12ga3cf2fdc",
      "name": "p-config-server",
      "metadata": {
         "shareable": true
      }
   }]
}

3. Service Instance Sharing Through CF CLI

With PCF 2.3 version, we got this service instance sharing option to do through CF CLI. We need to have Space Developer role in both spaces to share an instance from one space to another. We need to run the below command to do the same:

 > cf share-service SERVICE-INSTANCE -s OTHER-SPACE [-o OTHER-ORG]


To unshare the service instance, we need to run below command: 

 > cf unshare-service SERVICE-INSTANCE -s OTHER-SPACE [-o OTHER-ORG] [-f]

-f flag is used to force the unshare without confirmation.

4. Service Instance Sharing Through Apps Manager

With PCF 2.4, this option is also available through Apps Manager as well. So now its just a matter of clicking a button to share the service instance with other Orgs/spaces.
We need to go to the service instance which we want to share.


Click on SHARE SERVICE INSTANCE button to share the instance with other Orgs/Spaces. It will show all the orgs/spaces where we have access.


Please note that there is only share instance option available in Apps Manager. Unshare feature is still not available in Apps Manager.

5. Few Tips

 1. You may want to have the service broker return credentials with different permissions depending on which space an app is bound. For example, a messaging service may permit writes from the originating space and only reads from any spaces that the service is shared into.

To determine whether the space of the app is the same as the originating space of the service instance, the service broker can compare the context.space_guid and bind_resource.space_guid fields in the binding request. The context.space_guid field represents the space where the service instance was created, and bind_resource.space_guid represents the space of the app involved in the binding.
2. Just ensure that we don't have any service instance with the same name in the space where we are sharing.

3. Unsharing the service will delete all the bindings of the apps in the space it was shared into. So, we should ensure all the applications are taken care as they may fail.

6. Summary

To summarize, sharing instance feature is very useful in certain business use cases and with PCF 2.4 it has become very easy to use it. My two cent on the security side is that pay attention to ensure your service broker is implemented correctly to give the required permission only to Space, with which, the instance is shared


Sunday, February 10, 2019

1. Introduction

Groovy has two ways of instantiating strings. One is plain java.lang.String and second are groovy.lang.GString.
Plain string is represented with a single or double quote. However, the single quote doesn't support interpolation. Interpolation is supported only with a double quote and when it is present, then it becomes GString. In this article, we will see these different types of string representations in Groovy and how to concatenate them.


2. Types of Strings

So, there are 4 main types of string representations which are instantiated either through java.lang.String or groovy.lang.GString in Groovy - single-quoted string, double-quoted string, GString, and triple single-quoted string. Let's talk about them with some examples:
Let's first see the single-quoted string. It is also known as a plain string:

'My name is Joe Smith'

Here is an example for double-quoted string:

"My name is Joe Smith"

Double-quoted string also does support interpolation. When we add interpolation in it, it becomes GString. An interpolation is an act of replacing a placeholder in the string with its value upon evaluation of the string. The placeholder expressions are surrounded by ${}:


"My name is $name"

Now, we will see the example of a triple single-quoted string. It is used for multiline string, but it doesn’t support interpolation:

'''
My name is
Joe
Smith
'''
Now, let's see how to do concatenation of these different types of strings.

3. Using + Operator

Let's start with the simple '+' operator to see how we can concatenate two plain strings:

'My name is ' + first + ' ' + last

Note, here first and last are variables.
Let's write a simple test which sets the value of first and last variable and verify the return string is as expected:

name.first = 'Joe';
name.last = 'Smith';
def expected = 'My name is Joe Smith'
assertToString('My name is ' + first + ' ' + last, expected)

Similarly, we can use the double-quote instead of single-quote for concatenating the two plain strings.

4. Using GString

Let's now do the concatenation with GString:

"My name is $first $last"

The output of this string will be:

My name is Joe Smith

Note, here we have used the double-quote instead of single-quote. If we use single-quote, it will consider $first and $last as literals and output will be:

My name is $first $last

5. Using GString Closure

A closure in Groovy is an open, anonymous, block of code that can take arguments, return a value and be assigned to a variable.
In GString, when the placeholder contains an arrow, ${→}, the expression is actually a closure expression. Let's see the below example:

"My name is ${-> first} ${-> last}"

Let's do a simple test to understand the difference between GString and GString closure:

def first = "Joe";
def last = "Smith";
def eagerGString = "My name is $first $last"
def lazyGString = "My name is ${-> first} ${-> last}"

assert eagerGString == "My name is Joe Smith"
assert lazyGString == "My name is Joe Smith"

first = "David";

assert eagerGString == "My name is Joe Smith"
assert lazyGString == "My name is David Smith"

Here, eagerGString represents plain interpolation of GString and lazyGString represents interpolation with closure expression.
We also do notice here that in plain interpolation, the value is actually bound at the time of creation of the GString. That's why there is no change in eagerGString value even after changing the first variable value.
However, with a closure expression, the closure is called upon each coercion of the GString into String, resulting in an updated lazyGString containing the new value of the first variable.

6. Using String Concat Method

Now, let's see how to use String class concat() method to do the concatenation:

'My name is '.concat(first).concat(' ').concat(last)

7. Using LeftShift << Operator

Next, let's see the usage of the left shift '<<' operator to concatenate the strings:

'My name is ' << first << ' ' << last

String class also does have leftShift() method which overrides the << operator to provide an easy way of appending strings.

8. Using Array Join Method

We will now use an Array to concatenate the objects. An Array has a method called join() which concatenates the toString() representation of each item in the array, with the given String as a separator between each item.

['My name is', first, last].join(' ')

Note, here the separator is empty space.

9. Using Array Inject Method

Next, let's see how to use an inject(Object initialValue, Closure closure) method of Array to do the concatenation. This method iterates through the given Object, passing in the initial value to the closure along with the first item:

[first,' ', last]
  .inject(new StringBuffer('My name is '), { initial, name -> initial.append(name); return initial }).toString()

So, here it iterates through the array having [first, ' ', last]. It will pass the initial value as 'My name is ' and then keep appending each element of the array 'Joe' (value of first), ' ', 'Smith' (value of last).

10. Using StringBuilder

Now, let's use StringBuilder append() method for concatenating the String objects:

new StringBuilder().append('My name is ').append(first).append(' ').append(last)

11. Using StringBuffer

Next, let's see how to use StringBuffer append() method to do the concatenation:

new StringBuffer().append('My name is ').append(first).append(' ').append(last)

12. Concatenate Multiline String

Now, let's see how to do concatenation for triple single-quoted ('''  ''') strings:

name.first = '''
Joe
Smith
''';
name.last = 'Junior'

We can use any of the methods discussed in this article to concatenate this triple single-quoted string with other String objects. Let us take one example of how to do it using String concat() method:

'My name is '.concat(first).concat(' ').concat(last)

The output of the String will be:

'''My name is 
Joe
Smith
 Junior''';

Note, that there is an empty space before 'Junior'. concat(' ') method has added this. However, String does have stripIndent() method to remove such indentation.

13. Conclusion

To summarize, in this article we have seen various ways of doing the String concatenation in Groovy.

The full implementation of this tutorial can be found over on GitHub.

Thursday, February 7, 2019

Overview
Spring JdbcTemplate is a powerful mechanism to connect to the database and execute SQL queries. It internally uses JDBC API but eliminates a lot of problems of JDBC API. It helps to avoid writing boilerplate code for such as creating the connection, statement, closing resultset, connection, etc... 
With JdbcTemple, we generally do pass the parameter values with "?" (Question mark). However, it is going to introduce the SQL injection problem. So, Spring provides another way to insert data by the named parameter. In that way, we use names instead of "?". So it is better to remember the data for the column. This can be done using NamedParameterJdbcTemplate.
In this article, we will be learning how to use NamedParameterJdbcTemplate to pass named parameter.
Prerequisites
  • JDK 1.8
  • Spring-Boot Basic Knowledge
  • Gradle
  • Any IDE (Eclipse, VSD)
Gradle Dependency
This project needs a standard spring-boot-starter-web along with spring-boot-starter-jdbc and h2database driver. I am using spring-boot version springBootVersion = '2.1.2.RELEASE' for this exercise:
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-jdbc'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'com.h2database:h2'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
Configuration
We are using H2 as the database. And H2 provides a web interface called H2 Console to see the data. Let’s enable h2 console in the application.properties
/src/main/resources/application.properties:

# Enabling H2 Console
spring.h2.console.enabled=true
server.port=8100
Also, We have configured the port as 8100 for this application. We will see how to use the H2 Console later. For now, let's put other required code.
Domain
Let's create a domain class User. We will use this class to map with DB table USERS and insert each field of this object to this table:
public class User {
    private int id;
    private String name;
    private String address;
    private String email;
  // standard setters and getters
}
DAO
Now, let's create a DAO interface UserDao which defines what all methods need to be implemented:
public interface UserDao {
    public User create(final User user) ;
    public List<User> findAll() ;
    public User findUserById(int id);
}
DAOImpl
Now, let's create the implementation class. This will implement all the UserDao methods. Here, we will be using NamedParameterJdbcTemplate to create and retrieve the record. NamedParameterJdbcTemplate has many methods. We have used 3 methods here to demonstrate how to pass named parameters:
@Repository
public class UserDaoImpl implements UserDao {
    private final String INSERT_SQL = "INSERT INTO USERS(name, address, email)      values(:name,:address,:email)";
        private final String FETCH_SQL = "select record_id, name, address, email from users";
         private final String FETCH_SQL_BY_ID = "select * from users where record_id = :id";
    @Autowired
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
    
    public User create(final User user) {
        KeyHolder holder = new GeneratedKeyHolder();
        SqlParameterSource parameters = new MapSqlParameterSource()
        .addValue("name", user.getName())
        .addValue("address", user.getAddress())
        .addValue("email", user.getEmail());
        namedParameterJdbcTemplate.update(INSERT_SQL, parameters, holder);
        user.setId(holder.getKey().intValue());
return user;
}

    public User findUserById(int id) {
        Map<String, Integer> parameters = new HashMap<String, Integer>();
        parameters.put("id", id);
        return (User) namedParameterJdbcTemplate.queryForObject(FETCH_SQL_BY_ID, parameters, new UserMapper());
    }
}

class UserMapper implements RowMapper {
    @Override
    public User mapRow(ResultSet rs, int rowNum) throws SQLException {
        User user = new User();
        user.setId(rs.getInt("record_id"));
        user.setName(rs.getString("name"));
        user.setAddress(rs.getString("address"));
        user.setEmail(rs.getString("email"));
        return user;
    }

}
1. update() — We have used the update() method to insert the data to USERS table. If we used regular JDBCTemplate, we will be using:
INSERT_SQL  = "INSERT INTO USERS(name, address, email) values (?,?,?)"; 
But we have used NamedParameterJdbcTemplate so our query string will be like this:   

String INSERT_SQL = "INSERT INTO USERS(name, address, email)values(:name,:address,:email)"; 

We see that we are using the named parameters instead of "?".  
2. query() —  We have used the query() method to retrieve all the User records from USERS table. Here our query string will be:   
String FETCH_SQL = "select record_id, name, address, email from users";  
This will be the same as any other jdbcTemplate query. No special handling here.
3. queryForObject() — We have used queryForObject() method to retrieve User based on the record_id field. Here we will have query string as below:
 String FETCH_SQL_BY_ID = "select * from users where record_id = :id";

If you notice, here we have used the named parameter "id" instead of the "?".
Please also do note that we have used RowMapper to map the resultset with the User object.
Controller
Now, let's quickly expose this functionality through REST so that we can test it easily:
@RestController
public class UserController {
    @Autowired
    private UserDaoImpl userDao;
    @PostMapping("/users")
    public ResponseEntity<User> createUser() {
        User user   =   userDao.create(getUser());
        return ResponseEntity.ok(user);
    }
    @GetMapping("/users")
    public List<User> retrieveAllUsers() {
        return userDao.findAll();
    }
    @GetMapping("/users/{id}")
    public User retrieveUserById(@PathVariable int id ) {
        return userDao.findUserById(id);
    }
    private User getUser() {
        User user = new User();
        user.setAddress("Marathahalli, Bangalore");
        user.setEmail("rajesh.bhojwani@gmail.com");
        user.setName("Rajesh Bhojwani");
        return user;
    }
}
Build and Test
To build this application, we need to run Gradle build command:
 gradlew clean build 
It will generate the jar file under build/libs.
To start the application, we need to run the command:   
java -jar build/libs/springbootjdbc-0.0.1-SNAPSHOT.jar 
Now, before testing the application, we need to create the USERS table in the h2 database. So, let's start the h2-console at http://localhost:8100/h2-console.

Make sure JDBC URL is updated to jdbc:h2:mem:testdb. And, then click on Connect button.  Now, we can create the schema of the table USERS by running ddl statement.
 CREATE TABLE users (record_id bigint NOT NULL AUTO_INCREMENT, name varchar(100), address varchar(250), email varchar(100), PRIMARY KEY (record_id)); 

Once the table is created, now we can test our REST APIs to create and retrieve User record.
1. POST call -   http://localhost:8100/users  
2. GET call -    http://localhost:8100/users 
3. GET Call -   http://localhost:8100/users/1 

Conclusion

To summarize, we have seen in this article how to pass named parameters by using NamedParameterJdbcTemplate. 
As usual, the code can be found over Github.



Follow by Email

Followers

Popular Posts