Saturday, March 8, 2014

MBean Servers in Weblogic

Weblogic comes with three own MBeanServers, which are exported via RMI/IIOP as JSR-160 connectors. They can be looked up via a certain JNDI name as shown in the table below. Additionally, there is the ubiquitous PlatformMBeanServer.
MBean Server                                  JNDI Name
Domain Runtime MBean Server          weblogic.management.mbeanservers.domainruntime
Runtime MBean Server                  weblogic.management.mbeanservers.runtime
Edit MBean Server                          weblogic.management.mbeanservers.edit
PlatformMBeanServer                          —

The Runtime MBean Server specifies an individual application server, whereas the Domain Runtime MBean Server exposes the MBeans for all servers in a cluster. The Edit MBean Server is used for accessing and modifying the domain configuration.
Two access modes: There are two ways how the MBeanServers mentioned above can be exported for remote access:

  1. Via RMI/IIOP exported by Weblogic. This way, the three Weblogic MBeanServers (those with an JNDI name) can be exported (but not the PlatformMBeanServer directly). Advantage of this export is that it can be enabled with the admin console and that it includes the complete Weblogic security stack.
  2. Via RMI/JRMP exported by the JVM. This allows for the PlatformMBeanServer to be exported (but not the other, Weblogic specific MBeanServers). It gets enabled as usual by setting certain java defines as startup options and is secured the JDK way. A forthcoming blog will clarify how to setup security for JDK exported JSR-160 connectors.

Both methods are explained in detail in the following sections.
RMI/IIOP exported by Weblogic: First of all, some configuration items must be set to enable IIOP exported MBeans. In the admin console, check that following properties are set:

  • First, IIOP must be enabled: Domain (‘wl_server’) / Environment / Servers -> Server (‘examplesServer’) -> Protocols -> IIOP -> Enable IIOP
  • Allow for anonymous read access, if you want to monitor without sending credentials: Domain (‘wl_server’) -> Security -> General -> Anonymous Admin Lookup Enabled
  • If you want to secure IIOP access (or want to have write access), set the name and password of the default user: Domain (‘wl_server’) / Environment / Servers -> Server (‘examplesServer’) -> Protocols -> IIOP -> (Advanced) -> “Default IIOP Username” and “Default IIOP Password”

You need to restart the server if you change one of the options above. The JMX service URL for accessing Weblogic JMX connectors via IIOP looks like
service:jmx:rmi:///jndi/iiop://<server address>:<port>/<jndi name>
where the JNDI name is one of the MBeanServer’s JNDI name as described above. For example:
service:jmx:iiop:///jndi/iiop://bhut:7001/weblogic.management.mbeanservers.runtime

RMI/JRMP exported by JVM: As an alternative the usual way for exporting MBeans via RMI/JRMP can be used. This includes to set some java defines as startup options (probably within setDomainEnv.sh) like:
JAVA_OPTIONS="$JAVA_OPTIONS \ 
    -Dcom.sun.management.jmxremote \
    -Dcom.sun.management.jmxremote.port=9999 \
    -Dcom.sun.management.jmxremote.ssl=false \
    -Dcom.sun.management.jmxremote.authenticate=false"
jconsole service:jmx:rmi:///jndi/rmi://target:9999/jmxrmi
Unfortunately, by default, only the PlatformMBeanServer gets exported without any Weblogic specific MBean. However, there is a way to get to the Weblogic MBeans as described in the next section.

Using PlatformMBeanServer for Weblogic MBeans: For monitoring purposes having Weblogic runtime MBeans and JVM MXBeans in different MBeanServers which are exportable in different ways is quite annoying. However, for Weblogic there is a solution by configuring WLS to use the PlatformMBeanServer as it’s MBeanServer. With this configuration, your are able to access Weblogic MBeans from RMI/JRMP Service URLs (as it is used with ‘normal’ JMX clients like jconsole) and Java MXBeans from the RMI/IIOP connector used by Weblogic.

For this to work, you need to set Domain (‘wl_server’) > Configuration > General > (Advanced) > Platform MBeanServer enabled in the admin console for both WLS 9 and 10. Afterwards a server restart is required.

For WLS 10 an additional configuration parameter has to be set in order to let WLS use the PlatformMBeanServer for its runtime MBeans. The attribute PlatformMBeanServerUsed needs to be set to true on the JMXMBean (it is false by default). Unfortunately I didn’t find a way to set this attribute via the admin console, but only via the Weblogic scripting environment WLST. Assuming that your current working directory is you WLS 10 root directory, you should use wlst.sh to fire up the WLST in interactive mode and when the server is not running:
$ common/bin/wlst.sh
.....
wls:/offline> readDomain('samples/domains/wl_server')
wls:/offline/wl_server>cd('JMX')
wls:/offline/wl_server/JMX>ls()
drw-   NO_NAME_0
wls:/offline/wl_server/JMX>cd('NO_NAME_0')
wls:/offline/wl_server/JMX/NO_NAME_0>ls()
-rw-   CompatibilityMBeanServerEnabled               true
-rw-   DomainMBeanServerEnabled                      true
-rw-   EditMBeanServerEnabled                        true
-rw-   InvocationTimeoutSeconds                      0
-rw-   ManagementEJBEnabled                          true
-rw-   Name                                          null
-rw-   Notes                                         null
-rw-   PlatformMBeanServerEnabled                    false
-rw-   PlatformMBeanServerUsed                       false
-rw-   RuntimeMBeanServerEnabled                     true
wls:/offline/wl_server/JMX/NO_NAME_0>set('PlatformMBeanServerUsed','true')
wls:/offline/wl_server/JMX/NO_NAME_0>set('PlatformMBeanServerEnabled','true')
wls:/offline/wl_server/JMX/NO_NAME_0>updateDomain()
wls:/offline/wl_server/JMX/NO_NAME_0>closeDomain()
wls:/offline>exit()
The path to the domain (samples/domains/wl_server), an the name of the JMX-Bean (NO_NAME_0) might differ at your side, but I think, the idea is clear. As shown above you also can set PlatformMBeanServerEnabled via WLST as well.

Fire up the server and you should be ready for accessing WLS MBeans and JDK MXMBeans from within the same MBeanServer on Weblogic 10.

BTW, setting PlatformMBeanServerUsed via jmx4perl itself doesn’t work, because Weblogic needs some extra boilerplate (which I didn’t dive into) before configuration can be changed via JMX:
Part 1: Source:
  • How to implement a custom MBean to manage configuration associated with an application.
  • How to package the resulting code and configuration as part of the application's ear file.
  • How to register MBeans upon application startup, and unregistered them upon application stop (or undeployment).
  • How to use generic JMX clients such as JConsole to browse and edit our application's MBean.
Part 2: Source:
  • How to add localized descriptions to our MBean, MBean attributes, MBean operations and MBean operation parameters.
  • How to specify meaningful name to our MBean operation parameters.
  • We also touched on future enhancements that will simplify how we can implement localized MBeans.
Part 3: Source:
  • How to localize our MBean based on the calling client's locale as opposed to the server's locale.
  • How to take advantage of the default resource mapping provided by WebLogic Server to localize MBean descriptions.
  • How to write a simple client that access our MBean using a locale other than the server's locale.
  • How to set the locale associated with JConsole.
  • In this new blog entry we will demonstrate:
Part 4Source 
  • How to emit an AttributeChangeNotification each time a new property is added or changed through our MBean.
  • How to properly localize our notifications.
  • How to observe notification using JConsole.
  • How to write a client that subscribes to the notification emitted by our MBean.

Monday, February 24, 2014

J C O N S O L E

JConsole is shipped as part of the JDK, and doesn't require any specific download or installation. This blog demonstrates how simple it is to browse WebLogic MBeans using JConsole.
In order to connect to a WebLogic MBeanServer, JConsole needs to be started as follow:
$ jconsole -J-Djava.class.path=$JAVA_HOME/lib/jconsole.jar:$JAVA_HOME/lib/tools.jar:$WL_HOME/server/lib/wljmxclient.jar -J-Djmx.remote.protocol.provider.pkgs=weblogic.management.remote -debug
WL_HOME points to the WebLogic binary install.

The above uses WebLogic's thin client classes. In some cases when you access server side classes, or you want to take full advantage of the t3 protocol, you are required to use WebLogic's thick client classes. To do so, you first need to build wlfullclient.jar as follow:
cd $WL_HOME/server/lib
$ java -jar wljarbuilder.jar
You can then start JConsole as follow:
$ jconsole -J-Djava.class.path=$JAVA_HOME/lib/jconsole.jar:$JAVA_HOME/lib/tools.jar:$WL_HOME/server/lib/wlfulclient.jar -J-Djmx.remote.protocol.provider.pkgs=weblogic.management.remote -debug
wlfulclient.jar is not dependent on external jars, and can be copied to client machines. When using the thin client ( wljmxclient.jar ) you cannot just copy wljmxclient.jar to a client's machine as this jar references other jars as part of its manifest Class-Path entry. At the time of this writing, you also need to copy wlclient.jar
$ jconsole -J-Djava.class.path=C:/YYY/java/jdk1.6.0_45/lib/jconsole.jar;C:/Oracle/Middleware/wlserver_10.3/server/lib/wlfullclient.jar -J-Djmx.remote.protocol.provider.pkgs=weblogic.management.remote -debug

-J-Djmx.remote.protocol.provider.pkgs=weblogic.management.remote identifies the package implementing WebLogic's client side connectors code. For instance the 't3' or 'iiop' client connectors.

Finally the -debug flag is extremely handy when a connection failure occurs. In this case the corresponding stack trace is dumped on the console. Once JConsole is started select the Remote process connection, and fill out the target WebLogic's MBeanServer JMX URI, Username and Password fields.

The JMS Service URI: service:jmx:iiop://<hostname>:<port>/jndi/<mbeanserver-type>
$ service:jmx:iiop://cmpd06-po-3p.sys.comcast.net:17001/jndi/weblogic.management.mbeanservers.runtime

The protocol used to communicate with the remote WebLogic process. "iiop" in the above example. WebLogic supports "t3", "iiop" and "rmi". We won't touch further on this topic here.

The WebLogic process to connect to (host & port ). 140.87.10.42:12565 in the above example.
The port value is available from the <WLS_INSTANCE_HOME>/config/config.xml file:
<server>
  <name>cmpd06-po-3p</name>
  <listen-port>17001</listen-port>
  <listen-address>cmpd06-po-3p.sys.comcast.net</listen-address>
</server>
Make sure you look under the correct server if several servers are defined as part of your config.xml. For instance in the above case we are connecting to the server identified as "cmpd06-po-3p".

The MBeanServer to connect to: weblogic.management.mbeanservers.runtime. This identifies WebLogic's "Runtime" MBeanServer. This is the MBeanServer available from any WebLogic process, and that contains both WebLogic and user MBeans. WebLogic also offers two other MBeanServers that are only available from the Domain "AdminServer" process:

The "Domain Runtime" MBeanServer. It aggregates the MBeans registered on the domain's "Runtime" MBeanServers. So as long as a managed server is up, its MBeans can be accessed through the "Domain Runtime" MBeanServer. To connect to that MBeanServer, just use the following JMX URI:
service:jmx:iiop://cmpd06-po-3p.sys.comcast.net:17001/jndi/weblogic.management.mbeanservers.domainruntime
"17001" is the iiop port for my "AdminServer" install. Replace with your AdminServer's port as previously explained. Remember; only the AdminServer process runs the "Domain Runtime" MBeanServer.

The "Edit" MBeanServer. It contains the WebLogic Config MBeans that are used to configure the Domain. To connect to that MBeanServer, just use the following JMX URI:
service:jmx:iiop://cmpd06-po-3p.sys.comcast.net:17001/jndi/weblogic.management.mbeanservers.edit
"17001" is the iiop port for my "AdminServer" install. Replace with your AdminServer's port as previously explained. Remember; only the AdminServer process runs the "Domain Runtime" MBeanServer.
Note: One can also use "t3" or "rmi" as protocol in place of "iiop"

Finally provide the login and password values for the user associated with the connection. The WebLogic admin user is often used, but other users can be used as well. Depending on the authenticated user and his/her associated roles, operations on MBeans will be granted or denied.

JConsole connected to WebLogic's Runtime MBeanServer: If JConsole fails to connect, look at the stack trace dumped on the console. Make sure you specified the -debug flag when starting JConsole, or you will not see any meaningful information on the console. Common cause of connection failures include: wrong host/port; wrong login/password; jmx.remote.protocol.provider.pkgs not properly specified and incorrect ClassPath. Also note that the above instructions apply to WebLogic server 10.3.1 and above. 

JConsole's MBean tree preserves the key order used when building MBeans ObjectNames. The only exception is for the 'type' property which will be included first if present and the 'j2eeType' property which will be included second if present. In general I also use the 'name' property to identify different MBean instances while WebLogic MBeans use 'Type' and 'Name' properties for the same purpose. To ensure that JConsole's MBean tree is build with 'type' or 'Type' as first node and 'name' or 'Name' as its child I use the following command line: 
$ jconsole -J-Djava.class.path=$JAVA_HOME/lib/jconsole.jar:$JAVA_HOME/lib/tools.jar:$WL_HOME/server/lib/wljmxclient.jar -J-Djmx.remote.protocol.provider.pkgs=weblogic.management.remote -J-Dcom.sun.tools.jconsole.mbeans.keyPropertyList=type,Type,j2eeType,name,Name -debug

When connecting to WebLogic's "Domain Runtime" MBeanServer, one can also order by MBean 'Location' as follow: 
$ jconsole -J-Djava.class.path=$JAVA_HOME/lib/jconsole.jar:$JAVA_HOME/lib/tools.jar:$WL_HOME/server/lib/wljmxclient.jar -J-Djmx.remote.protocol.provider.pkgs=weblogic.management.remote -J-Dcom.sun.tools.jconsole.mbeans.keyPropertyList=Location,type,Type,j2eeType,name,Name -debug

Aside from browsing and editing MBeans, JConsole can be used to monitor WebLogic processes resource usage: Memory, Threads, Class loading. Consult JConsole's documentation for more information. 

Configurations for remote JMX access to WebLogic

To celebrate support for MissionControl in the Oracle JDK (7u40 and forwards), this post will illustrate how to access a remote JVM running WebLogic can be accessed using using MissionControl and JConsole.

Unsecure MissionControl setup

This setup can be used to access a remote JVM running WebLogic using MissionControl as the JMX client. The setup is unsecure, i.e. SSL and authentication is disabled. The WebLogic server is assumed to listen on listen address 10.00.00.145.

Server configuration

Add these properties to the WebLogic start arguments:
-Djavax.management.builder.initial=weblogic.management.jmx.mbeanserver.WLSMBeanServerBuilder -Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=7091 -Dcom.sun.management.jmxremote.rmi.port=7091 -Djava.rmi.server.hostname=10.00.00.145 -Dcom.sun.management.jmxremote.local.only=false

The argument javax.management.builder.initial enables usage of the WebLogic platform MBeans. Failure to set this argument will result in a BEA-141277 warning when WebLogic starts.

The com.sun.management.jmxremote.rmi.port argument defines the port where the RMI server and remote objects are exported to by the RMI stack. Used in conjunction with the com.sun.management.jmxremote.port argument, this enables access to the JVM through a single TCP port which is required in a firewall enriched environment.
The arguments java.rmi.server.hostname and com.sun.management.jmxremote.local.only
have been observed to be required if the server is running in a virtualized setup based on VirtualBox&Vagrant.

Client configuration

Create a connection:
Host: 10.00.00.145
Port 7091
Open the JMX Console or the MBean Browser.

Unsecure JConsole setup

This setup can be used to access a remote JVM running WebLogic using JConsole as the JMX client. The setup is unsecure, i.e. SSL and authentication is disabled. The WebLogic server is assumed to listen on listen address 10.00.00.145.

Server configuration

Add these properties to the WebLogic start arguments:
-Djavax.management.builder.initial=weblogic.management.jmx.mbeanserver.WLSMBeanServerBuilder -Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=7091 -Dcom.sun.management.jmxremote.rmi.port=7091 -Djava.rmi.server.hostname=10.00.00.145 -Dcom.sun.management.jmxremote.local.only=false

Client configuration

JConsole is configured to use the WebLogic implementation of the network protocols using the jmx.remote.protocol.provider.pkgs system argument. This requires that the libraries wljmxclient.jar and wlclient.jar are located in the WL_HOME directory. Here's a Windows script to start JConsole with the WebLogic network protocol implementations:
set JAVA_HOME=C:\Program Files\Java\jdk1.7.0_45 
set WL_HOME=C:\work\jconsole 
"%JAVA_HOME%\bin\jconsole.exe" -J-Djava.class.path="%JAVA_HOME%\lib\jconsole.jar;%WL_HOME%\server\lib\wljmxclient.jar" -J-Djmx.remote.protocol.provider.pkgs=weblogic.management.remote -debug
Access WebLogic using the URL: 10.00.00.145:7091
Requires no user credentials since authentication is disabled.

Unsecure JConsole setup with T3

This is a variation of the previous setup. It allows access to the JVM running the WebLogic administration server using the JConsole as the JMX client. The server is accessed using the T3 protocol. Authentication is required with a WebLogic user with administrative privileges. The WebLogic server is assumed to listen on 10.00.00.144:7001

Server configuration

Same server setup as in the previous setup.

Client configuration

JConsole is configured to use the WebLogic implementation of the T3 protocol using the jmx.remote.protocol.provider.pkgs system argument. This requires that the WL_HOME directory to point to the WebLogic home directory. Here's a Windows script to start JConsole with the WebLogic T3 protocol implementation:
set JAVA_HOME=C:\Program Files\Java\jdk1.7.0_45
set WL_HOME=C:\Oracle\Middleware\wlserver
"%JAVA_HOME%\bin\jconsole.exe" -J-Djava.class.path="%JAVA_HOME%\lib\jconsole.jar;%WL_HOME%\server\lib\wljmxclient.jar" -J-Djmx.remote.protocol.provider.pkgs=weblogic.management.remote -debug
Access WebLogic using the URL: service:jmx:t3://10.00.00.144:7001/jndi/weblogic.management.mbeanservers.edit
Requires user credentials despite authentication being disabled.

I can get JDeveloper's external tools capability to do the lifting.

Very simple this. Just choose Tools > External Tools from the menu and press New.  Then run through the wizard:

  1. Type is External Program
  2. Program Options > Program Executable = jconsole
  3. Program Options > Arguments =  (All on one line of course, reformatted here for readability)

 -J-Djava.class.path=${java.path}/lib/jconsole.jar:${java.path}/lib/tools.jar: ${prop:name=weblogic.home}/lib/wljmxclient.jar -J-Djmx.remote.protocol.provider.pkgs=weblogic.management.remote 

And that's it.  JDeveloper helpfully substitutes both the Java location and the WebLogic location for us saving all that hunting around.  

Tip: ${java.path} not expanding correctly (or rather expanding to null). Before running the tool command with the macro make sure that you have a project open and selected as the actual java path is obtained in the context of the JRE version used by the selected project. (Project Properties > Libraries and Classpath > Java SE Version).

Sample Weblogic JMX Client

Our goal is to implement a simple WebLogic JMX client that can be used as a starting point to write any WebLogic JMX client. We will look at the client's code. The classpath used to compile and run the code. The different WebLogic MBeanServers and associated JMX URI's the JMX Client can connect to.
Let's directly dive in the client's code below:
= = = = = = = = = = = = = = = = = = =
package blog.wls.jmx.client;

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXServiceURL;
import javax.management.remote.JMXConnectorFactory;
import java.util.Hashtable;
import java.util.Set;

public class JMXClient {
public static void main(String[] args) throws Exception {
        JMXConnector jmxCon = null;
        try {
            JMXServiceURL serviceUrl = new JMXServiceURL("service:jmx:iiop://127.0.0.1:7001/jndi/weblogic.management.mbeanservers.runtime");
            System.out.println("Connecting to: " + serviceUrl);
            Hashtable env = new Hashtable();
            env.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,"weblogic.management.remote");
            env.put(javax.naming.Context.SECURITY_PRINCIPAL, "weblogic");
            env.put(javax.naming.Context.SECURITY_CREDENTIALS, "welcome1");

            jmxCon = JMXConnectorFactory.newJMXConnector(serviceUrl, env);
            jmxCon.connect();
            MBeanServerConnection con = jmxCon.getMBeanServerConnection();
            Set<ObjectName> mbeans = con.queryNames(null, null);
            for (ObjectName mbeanName : mbeans) {
                System.out.println(mbeanName);
            }
        }
        finally {
            if (jmxCon != null)
                jmxCon.close();
        }
    }
}
= = = = = = = = = = = = = = = = = = =
Let's take a quick look at the above code.
JMXServiceURL serviceUrl = new JMXServiceURL("service:jmx:iiop://127.0.0.1:7001/jndi/weblogic.management.mbeanservers.runtime");
The JMX service URI identifies the following:
  • The protocol used to communicate with the remote WebLogic process. "iiop" in the above example. WebLogic supports "t3", "iiop" and "rmi". We won't touch further on this topic here.
  • The WebLogic process to connect to (host & port ). "127.0.0.1:7001" in the above example.The port value is available from the <WLS_INSTANCE_HOME>/config/config.xml file.
  • The MBeanServer to connect to: " weblogic.management.mbeanservers.runtime". This identifies WebLogic's "Runtime" MBeanServer. This is the MBeanServer available from any WebLogic process, and that contains both WebLogic and user MBeans.
    • Hashtable env = new Hashtable();
    • env.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,"weblogic.management.remote");
    • env.put(javax.naming.Context.SECURITY_PRINCIPAL, "weblogic");
    • env.put(javax.naming.Context.SECURITY_CREDENTIALS, "welcome1");
The above code specifies properties associated with the connection. "weblogic.management.remote" identifies the package implementing WebLogic's client side connector code. For instance the 't3' or 'iiop' client connector. "weblogic" and "welcome1" are the login/password associated with the user originating the JMX connection.

In the rest of the code we establish the JMX connection, and then retrieve the ObjectNames for all the MBeans registered in the "Runtime" MBeanServer. The ObjectNames are then displayed on the console. We also make sure we release the connection in a finally block to avoid leaking any resource.

The code doesn't contain any WebLogic specific classes, and can be compiled as follow:
$ javac -d . blog/wls/jmx/client/JMXClient.java

Executing the code requires to add WebLogic client side classes to the execution ClassPath. We need to include the WebLogic JMX connector client side classes. Remember we specified those in the environment properties passed to the JMXConnectorFactory. Below is the command I used:
$ java -classpath .:$WL_HOME/server/lib/wljmxclient.jar blog/wls/jmx/client/JMXClient

WL_HOME points to the WebLogic binary install.
The above uses WebLogic's thin client classes. In some cases when you access server side classes, or you want to take full advantage of the t3 protocol, you are required to use WebLogic's thick client classes. To do so, you first need to build wlfullclient.jar as follow:
cd $WL_HOME/server/lib
java -jar wljarbuilder.jar

You can then execute the JMX Client as follow:
java -classpath .:$WL_HOME/server/lib/wlfullclient.jar  blog/wls/jmx/client/JMXClient

You can also bundle wlfulclient.jar with your client code. When using the thin client you cannot just bundle wljmxclient.jar with you client code, as this jar references other jars as part of its manifest Class-Path entry. At the time of this writing, you also need to bundle wlclient.jar

At this point we are now able to connect to WebLogic's "Runtime" MBeanServer. Each WebLogic process contains a "Runtime" MBeanServer in which local WebLogic MBeans and user-defined application MBeans are registered. WebLogic also offers two other MBeanServers that are only available from the Domain "AdminServer" process:
  • The "Domain Runtime" MBeanServer. It aggregates the MBeans registered on the domain's "Runtime" MBeanServers. So as long as a managed server is up, its MBeans can be accessed through the "Domain Runtime" MBeanServer. To connect to that MBeanServer, just use the following JMX URI:
    • service:jmx:iiop://127.0.0.1:7002/jndi/weblogic.management.mbeanservers.domainruntime
      • "7002" is the iiop port for my "AdminServer" install. Replace with your AdminServer's port as previously explained. Remember; only the AdminServer process runs the "Domain Runtime" MBeanServer.
  • The "Edit" MBeanServer. It contains the WebLogic Config MBeans that are used to configure the Domain. To connect to that MBeanServer, just use the following JMX URI:
    • service:jmx:iiop://127.0.0.1:7002/jndi/weblogic.management.mbeanservers.edit 
      • "7002" is the iiop port for my "AdminServer" install. Replace with your AdminServer's port as previously explained. Remember; only the AdminServer process runs the "Domain Runtime" MBeanServer.
Note: One can also use "t3" or "rmi" as protocol in place of "iiop"

The rest of the client's code remains unchanged. Only the JMX URI needs to be changed to connect to different MBeanServers.

References:

Sunday, February 9, 2014

JBoss AS 7 / WildFly in Domain Mode

One of the best features which JBoss AS 7 / Wildfly came up was the domain mode, which is been used when you are looking for a single point of controller over all the servers, which can be running on the same/different boxes.

Most people think that domain mode has to be used when they want clustering which is not true, the main reason domain mode was created to control all the servers which can be in cluster/non-cluster from one point which was not available in the earlier versions of JBoss.

So in this article we would be showing you how can we start JBoss servers in a domain mode in two different boxes which are not in cluster. Once you are able to do it with box-2 you can add other host controller on on different boxes as shown in the below image.

Things to Remember

We need to keep in mind the following 4 things for successfully start JBoss AS 7 in domain mode.
Step 1: Add a name to your host controller in the “host” tag:
           <host name="host1" xmlns="urn:jboss:domain:1.2"> 

Step 2: Make sure you replace the “<local/>” tag from the “domain-controller” element in the “host.xml” file, when you are creating a host controller:
    <domain-controller>
              <remote host="${jboss.domain.master.address:<IP_ADDRESS-DOMAIN_CONTROLLER>}" port="${jboss.domain.master.port:<NATIVE_PORT-  

                                     DOMAIN_CONTROLLER>}" security-realm="ManagementRealm"/>
     </domain-controller>


Step 3: Create a “Management User” in the Domain controller, using the same host name (i.e. “host1″)

Step 4: Now convert that password (i.e password given for the host name in step-3 “host1″) into Base64 encoded password which has to be given in the host controller.
<server-identities>
    <!-- Replace this with either a base64 password of your own, or use a vault with a vault expression -->
    <secret value="aG9zdDFwYXNzd29yZA=="/>
</server-identities>

Box-1 (Domain Controller – 10.252.168.173)

bhmed-dt-1q.zone7.downingtown.pa.ula.comcast.net [10.252.168.173] - bhmed-dt-1q.cable.comcast.com
On Box-1 we would setup the domain controller, which would be using the “domain.xml” file and the “host.xml” file which defines that on this box we have the domain controller.

Step 1: From “/jboss-as-7.1.1.Final/bin” start the domain controller using the below command
./domain.sh -b 10.252.168.173  -bmanagement 10.252.168.173

Step 2: Now you would have to create users for “Management User”, using the same host names which you are planning to control (i.e. suppose its “host1″)
./add-user.sh
What type of user do you wish to add?
 a) Management User (mgmt-users.properties)
 b) Application User (application-users.properties)
(a): a
Enter the details of the new user to add.
Realm (ManagementRealm) :
Username : host1
Password : host1password
Re-enter Password : host1password
About to add user 'host1' for realm 'ManagementRealm'
Is this correct yes/no? yes
Added user 'host1' to file '/user/jboss-as-7.1.1.Final/standalone/configuration/mgmt-users.properties'
Added user 'host1' to file '/user/jboss-as-7.1.1.Final/domain/configuration/mgmt-users.properties'
 

Note: You should NOT use any special characters when you are giving a host name, because during creating a “Managment User” you would get the following error
* Error *
JBAS015239: Only alpha/numeric usernames accepted.
That’s it from domain controller side

Base64 Encrypt Password Generator

There are lot of websites available which would help you generate base64 value from clear text, however you can also use one of our code which we have created, which would do the same for you. We are using commons-codec.jar for this and below Base64EncryptPassword.java and Base64Password.sh files
import org.apache.commons.codec.binary.Base64;
public class Base64EncryptPassword {
     public static void main(String ar[]) throws Exception {
        byte[] encodedByte = org.apache.commons.codec.binary.Base64.encodeBase64(ar[0].getBytes());
        String encodedBase64String = new String(encodedByte);
        System.out.println("\n=========================================================");
        System.out.println("Your  Clear Text Password is :     "+ar[0]);
        System.out.println("Base64 Encrypted Password is :     "+encodedBase64String);
        System.out.println("=========================================================\n");
       }
  }


Base64Password.sh
#!/bin/sh
export JAVA_HOME=/user/jdk1.6.0_21   #<= change this path
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=commons-codec.jar:.
 

java Base64EncryptPassword $1

Note: Make sure that you keep all the files commons-codec.jar , Base64EncryptPassword.class and Base64Password.sh in the same folder when you run below command.
/Base64EncryptPassword]$ ./Base64Password.sh host1password
=========================================================
Your  Clear Text Password is :     host1password
Base64 Encrypted Password is :     aG9zdDFwYXNzd29yZA==
=========================================================

Box-2 (Host Controller – 10.252.168.174)

bhmed-dt-2q.zone7.downingtown.pa.ula.comcast.net [10.252.168.174] - bhmed-dt-2q.cable.comcast.com
On Box-2 we would setup the host controller, which would NOT be using its “domain.xml” file, but will use the “host.xml” which has the domain controllers details running on Box-1, this way domain controller would be able to controller its hosts.
Step 1: First we would need to give a name for the host controller in the “host” tag
<host name="host1" xmlns="urn:jboss:domain:1.2">

Step 2: As we need to communicate with the Domain controller we would have to make sure we replace the “<local/>” tag from the “domain-controller” element in the “host.xml” file, when you are creating a host controller.
<domain-controller>
    <remote host="${jboss.domain.master.address:
10.252.168.173}" port="${jboss.domain.master.port:9999}" security-realm="ManagementRealm"/>
</domain-controller>


Note: You should make sure that you have added and give the correct value for “security-realm” or else you would get the following error during starting the host controller.
[Host Controller] 23:09:43,584 ERROR [org.jboss.remoting.remote.connection] (Remoting "host1:MANAGEMENT" read-1) JBREM000200: Remote connection failed: javax.security.sasl.SaslException: Authentication failed: all available authentication mechanisms failed
[Host Controller] 23:09:43,593 ERROR [org.jboss.as.host.controller] (Controller Boot Thread) JBAS010901: Could not connect to master. Aborting. Error was: java.lang.IllegalStateException: JBAS010942: Unable to connect due to authentication failure.


Step 3: Now the password which was given during creating the “Management User” in domain controller (i.e password given for the host name in step-2 “host1password“) has to be converted into Base64 encoded password which has to be given in the host controller. By doing this domain controller would be able to know that an authorized host is trying to connect.
<server-identities>
    <!-- Replace this with either a base64 password of your own, or use a vault with a vault expression -->
    <secret value="aG9zdDFwYXNzd29yZA=="/>
</server-identities>


Step 4: All the required configuration has been done, now its time to start your host controller using the below command
./domain.sh -b 10.252.168.174 -bmanagement 10.252.168.174 -Djboss.domain.master.address=10.252.168.173 -Djboss.domain.master.port=9999

Once everything comes up you can see the below logging inside the domain controller console, which means that our configuration works properly as well you can also login into admin console which would be running on “http://10.252.168.173:9090/console” and you would see “host1″ servers in it.

[Host Controller] 22:19:17,250 INFO  [org.jboss.as.domain] (domain-mgmt-handler-thread - 1) JBAS010918: Registered remote slave host "host1", JBoss AS




Sunday, January 26, 2014

GLANCE @ GIT


Create a new repository

Create a new directory, open it and perform a "$ git init" to create a new git repository.
eg:
$ mkdir example.git
$ cd example.git
$ git init [--bare]

Checkout a repository

Create a working copy of a local repository by running the command
"$ git clone /path/to/repository
when using a remote server, your command will be
"$ git clone username@host:/path/to/repository".

Workflow

Your local repository consists of three "trees" maintained by git. the first one is your Working Directory which holds the actual files. the second one is the Index which acts as a staging area and finally the HEAD which points to the last commit you've made.






Add & Commit 

You can propose changes (add it to the Index) using
"$ git add <filename>"
"$ git add *"
This is the first step in the basic git workflow. To actually commit these changes use
"$ git commit -a -m "Commit message"
Committing your changes "$ git commit"
Committing files from working directory skipping staging area " $ git commit -a"
Viewing commit history: "$ git log"

Now the file is committed to the HEAD, but not in your remote repository yet.

Pushing Changes

Your changes are now in the HEAD of your local working copy. To send those changes to your remote repository, execute:
"$ git push origin master"
Change master to whatever branch you want to push your changes to.
If you have not cloned an existing repository and want to connect your repository to a remote server, you need to add it with
"$ git remote add origin <server>"
Now you are able to push your changes to the selected remote server

Forking

Forking and updating a repo:

  1. Fork this repository: This is a GitHub operation, in which you are making a copy of Joe's repository (including the files, commit history, issues, and more). This repository now lives in your GitHub account. Nothing has yet happened to your local computer.
  2. Clone your repo: This is a Git operation, in which you are using Git to tell GitHub "please send me a copy of my repo" The repo is now stored on your local computer.
  3. Update some files: You can now make updates to the files in whatever program or environment you like.
  4. Commit your changes: This is a Git operation, in which you are using Git to tell GitHub "here are my changes" Pushing does not happen automatically, so until you do this step, GitHub does not know about your commits.
  5. Push your changes to your github repo: This is a Git operation, in which you are using Git to tell GitHub "here are my changes" Pushing does not happen automatically, so until you do this step, GitHub does not know about your commits.
  6. Send a pull request to Joe: If you think that Joe might like to incorporate your changes, you send him a pull request. This is a GitHub operation, in which you are communicating your changes to Joe, and "requesting" that he "pull" form your repo. It is up to him whether he pulls from you or not.

Syncing a fork

Let's say that Joe and other contributors have made some more updates to the game, and you've thought of some more updates you'd like to make. Before you do anything else, it's best to "sync your fork" so that you are working on the latest copy of the files. Here's what you do:
  1. Fetch changes from Joe's repo: This is a Git operation, in which you are using Git to tell GitHub that you would like to retrieve the latest files from Joe's repo.
  2. Merge those changes into your repo: This is a Git operation, in which you are updating the repo on your local computer with those changes (which have been temporarily stored in a "branch"). Note: Steps 1 and 2 are often combined into a single Git operation called a "pull".
  3. Push the updates to your GitHub repo:(optional): Remember that your local computer does not automatically update your GitHub repo. Therefore, the only way to get your GitHub repo up-to-date is by pushing up the latest changes. You can either do this right away, or you can wait until you have made some updates of your own and committed them locally.
Take note of the contrast between the workflow for forking and the workflow for syncing: When you initially fork a repo, the flow of information is from Joe's repo to your repo, and then down to your local computer. But after that initial process, the flow of information is from Joe's repo to your local computer, and then up to your repo.

Branching

Branches are used to develop features isolated from each other. The master branch is the "default" branch when you create a repository. Use other branches for development and merge them back to the master branch upon completion.
create a new branch named "feature_x" and switch to it using
"$ git checkout -b feature_x"
switch back to master
"$ git checkout master"
and delete the branch again
"$ git branch -d feature_x"
a branch is not available to others unless you push the branch to your remote repository
"$ git push origin <branch>"
Checking Status of the files: "$ git status "

Update & Merge




To update your local repository to the newest commit, execute
[fetch+merge]"$ git pull"
[fetch + rebase] "$git pull --rebase"
in your working directory to fetch and merge remote changes.
to merge another branch into your active branch (e.g. master), use
"$ git merge <branch>"
in both cases git tries to auto-merge changes. Unfortunately, this is not always possible and results in conflicts. You are responsible to merge those conflicts manually by editing the files shown by git. After
changing, you need to mark them as merged with
"$ git add <filename>"
before merging changes, you can also preview them by using
"$ git diff <source_branch> <target_branch>"

Tagging

it's recommended to create tags for software releases. this is a known concept, which also exists in SVN. You can create a new tag named 1.0.0 by executing
"$ git tag 1.0.0 1b2e1d63ff"
the 1b2e1d63ff stands for the first 10 characters of the commit id you want to reference with your tag. You can get the commit id with
"$ git log"
you can also use fewer characters of the commit id, it just has to be unique.

Replace local changes

In case you did something wrong (which for sure never happens ;) you can replace local changes using the command
"$ git checkout -- <filename>"
this replaces the changes in your working tree with the last content in HEAD. Changes already added to the index, as well as new files, will be kept.
If you instead want to drop all your local changes and commits, fetch the latest history from the server and point your local master branch at it like this
"$ git fetch origin"
"$ git reset --hard origin/master"

Useful Hints

gitk: built-in git GUI
Use colorful git output: "$ git config color.ui true"
Show log on just one line per commit: "$ git config format.pretty oneline"
Use interactive adding: "git add -i"

Exceptions:

#1: fatal: This operation must be run in a work tree [duplicate]
Explanation: You repository is bare, i.e. it does not have a working tree attached to it. You can clone it locally to create a working tree for it, or you could use one of several other options to tell Git where the working tree is, e.g. the --work-tree option for single commands, the GIT_WORK_TREE environment variable, or the core.worktree configuration option.
"$ git config core.bare false"

Quick Reference:

Cloning a remote repo (that you created or forked on GitHub)

  • git clone < your-repo-URL >: copies your remote repo to your local machine (in a subdirectory with the repo's name), and automatically creates an "origin" handle
  • git remote add upstream < forked-repo-URL >: adds an "upstream" handle for the repo you forked
  • git remote -v: shows the handles for your remotes
  • git remote show < handlename >: inspect a remote in detail

Tracking, committing, and pushing your changes

  • git add < name >: if untracked, start tracking a file or directory; if tracked and modified, stage it for committing
  • git reset HEAD < name >: unstage a changed file
  • git commit -m "message": commits everything that has been staged with a message
    • -a -m "message": automatically stages any modified files, then commits
    • --amend -m "new message": fixes the message from the last commit
  • git push origin master: pushes your commits to the master branch of the origin

Syncing your local repo with the upstream repo

  • git fetch upstream [master]: fetch the upstream and store its master branch in "upstream/master"
  • git merge upstream/master: merge that branch into the working branch

Viewing the status of your files

  • git status: check which files have been modified and/or staged since the last commit
  • git diff: shows the diff for files that are modified but not staged
    • --staged: shows the diff for files that are staged but not committed

Viewing the commit history

  • git log: shows the detailed commit history
    • -1: only shows the last 1 commit
    • -p: shows the line diff for each commit
    • -p --word-diff: shows the word diff for each commit
    • --stat: shows stats instead of diff details
    • --name-status: shows a simpler version of stat
    • --oneline: just shows commit comments
  • gitk: open a visual commit browser

Managing branches

  • git branch: shows a list of local branches
    • < branchname >: create a new branch with that name
    • -d < branchname >: delete a branch
    • -v: show the last commit on each local branch
    • -a: show local and remote branches
    • -va: show the last commit on each local and remote branch
    • --merged: list which branches are already merged into the working branch (safe to delete)
    • --no-merged: list which branches are not merged into the working branch
  • git checkout < branchname >: switch the HEAD pointer to a different branch
    • -b < branchname >: create a new branch and switch to it

Removing, deleting, and reverting files

  • git rm < name >: deletes that file from the disk, then stages its deletion
    • --cached < name >: stops tracking a file, then stages its deletion (but does not delete it from the disk)
  • git mv < oldname > < newname >: renames the file on disk, then stages the deletion of the old name and addition of the new name
  • git checkout -- < name >: revert a modified file on disk back to the last committed version

Other basic commands

  • git init: initialize Git in an existing directory
  • git config --list: shows your Git configuration
  • touch .gitignore: create an empty .gitignore file

GIT Daily workflow



    Whole Idea is to keep your repository latest and pull others changes and resolve conflict if any:

    Note:
    1. $ git branch (is local branch on your machine)
    2. $ git fetch origin (Remote Branch to your reposioty)

    1. $ git fetch upstream (Remote Branch to company/project repository)


    1. Takes latest from Remote (upstream):
      1. $ git fetch upstream master
      2. $ git merge upstream/master
    2. Resolve conflicts:
      1. $ git add .
      2. $ git commit -a -m "your_message"
      3. $ git status
    3. Bring these changes to your remote repository (from your local).
      1. $ git push origin master # git push origin BRANCH_NAME

    Q. How to clone and remote repository?
    Check:           
    $ git branch -r # to list all remote branches only.

    $ git remote -v # check list of all remote branches


    Origin: $ git clone https://git.company.com/andixit/mkp.git # this is automatically set as origin.
    Upstream: $ git remote add upstream https://git.company.com/equinix/mkp.git # this will add upstream branch.

    Q. List all branch Local or remote?
    $ git branch -a # to check all branches local or remote.

    Q. How to remove / delete a repository?
    A. there could be three kind of delete / remove repository path in GIT:

    /apps/opt/projects/marketplace/services/report-data-service>git push origin -d MKP-5.3

    1. Remote:
    $ git push origin --delete <branch_name>
    $ git branch -d <branch_name>
    > git push origin --delete <branch>  # Git version 1.7.0 or newer
    > git push origin :<branch>          # Git versions older than 1.7.0

    2. Local:
    $ git branch --delete <branch>
    $ git branch -d <branch> # Shorter version
    $ git branch -D <branch> # Force delete un-merged branches

    3. Deleting a local remote-tracking branch:
    $ git branch --delete --remotes <remote>/<branch>
    $ git branch -dr <remote>/<branch> # Shorter

    $ git fetch <remote> --prune # Delete multiple obsolete tracking branches
    $ git fetch <remote> -p      # Shorter


    Q. How to checkout a specific revision?

    $ git clone https://git.company.com/anupdixit/mkp.git
    $ git checkout usermanagment

    # checkout a particular revision

    $ git checkout <sha1>
    $ git checkout 17a5d87d31aab43e9e6b8eb51bf1516b13ec78c6
    Q. How to switch to already existing branch?
    $ git checkout anup-dev # switched to anup-dev # use this command if branch already created.

    Q. How to create a new feature specific branch?
    $ git checkout –b anup-dev # execute this command to create a new feature specifc branch from current checkout branch.
    or use following 2 commnad equivalent to above command:
    1. $ git branch anup-dev
    2. $ git checkout anup-dev


    Q. Copy code from one local branch to another local branch?

    Go to the target branch (git checkout target) and merge the code-having branch (git merge code-having). then, if needed, push the updated target branch to its remote.
    eg. feature specific code is checked in to anup-dev, now i want to move it to user’s remote master.
    $ git checkout master # first go to target branch
    $ git merge anup-dev # merge the changes from branch that have code.


    Q. Copy code from one Remote branch to another Remote branch?

    A. $ git push origin anup-dev:master # push changes to master from anup-dev in origin

    Q. How to tag your release?
    1. Checkout A Tag:

      $ git checkout -b <NEW_BRANCH_NAME> <TAG_NAME>
      $ git checkout -b MKP_R3.10_UAT_RC5 MKP_R3.10_UAT_RC4
    2. Tag A Release:
      $ git tag -a <TAG_NAME> -m <TAG_MESSAGE>
      $ git push origin <TAG_NAME>

      Eg. $ git push origin MKP_R4.0_RC5_23052012
      $ git push origin --tags
    eg:
      $ git tag -a MKP_R3.10_UAT_RC5 -m "RC5"
      $ git push origin MKP_R3.10_UAT_RC5

    Q. How to undo a git commit?

    There are two ways to "undo" your last commit, depending on whether or not you have already made your commit public (pushed to your remote repository):

    1. Undo from local commit: Lets say I committed locally, but now want to remove that commit.

    $ git log

       commit 101: bad commit    # latest commit, this would be called 'HEAD'
       commit 100: good commit   # second to last commit, this is the one we want

    To restore everything back to the way it was prior to the last commit, we need to reset to the commit before HEAD:
    $ git reset --soft HEAD^     # use --soft if you want to keep your changes
    $ git reset --hard HEAD^     # use --hard if you don't care about keeping the changes you made
    Now git log will show that our last commit has been removed.

    2. Undo a public commit: If you have already made your commits public, you will want to create a new commit which will "revert" the changes you made in your previous commit (current HEAD).
    $ git revert HEAD
    Your changes will now be reverted and ready for you to commit:
    $ git commit -m 'restoring the file I removed by accident
    $ git log
       commit 102: restoring the file I removed by accident
       commit 101: removing a file we dont need
       commit 100: adding a file that we need
    3. Undo last 5 commits: $ git reset --hard 5a7404742c85
    HEAD is now at 5a74047 Added one more page to catalogue
    $ git push origin master --force
    Total 0 (delta 0), reused 0 (delta 0)
    remote: bb/acl: neoneye is allowed. accepted payload.
    To git@github.org:thecompany/mkp.git
    + 09a6480...5a74047 master -> master (forced update)
    Q. Git Reset:
    $ git reset --hard # removes staged and working directory changes
    ## !! be very careful with these !! you may end up deleting what you don't want to read comments and manual. $ git clean -f -d # remove untracked $ git clean -f -x -d # CAUTION: as above but removes ignored files like config. $ git clean -fxd :/ # CAUTION: as above, but cleans untracked and ignored files through the entire repo
    (without :/, the operation affects only the current directory)

    Q. How to find difference between different branch?
    A. $ git diff MKP-5.3 master services\report-data-service

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  - - -
    $ git log -5 —oneline # check last 5 changes to repository

    https://github.com
    Username:
    First you need to tell git your name, so that it can properly label the commits you make.
    $ git config --global user.name “your name here”
    $ Sets the default name for git to use when you commit.

    Email: Git saves your email into the commits you make. We use the email address to associate your commits with your github account.
    $ git config --global user.email “your_email@example.com”
    $ sets the default email for git to use when you commit.

    $ git clone <url_from_github>
    # give password when required

    # no need to run init because it already been initialized.
    $ git remote -v # check git remote location
    $ git remote add origin <url_from_github>

    $ git status # to check status of new and modified file
    $ git add . # add everything in current directory.

    $ git commit -m “Committing file”
    $ git status # to confirm nothing else to commit.
    $ git log # to check everything is committed

    $ git push origin master # push master to origin (remote) - give password when required.

    Sync Fork with upstream require 2 operation:
    1. Fetch:  from remote to local
    2. Merge: merge changes and differences in local with others changes.
    3. Push: once satisfied push changes to remote repo. 

    $ git remote -v
    $ git remote add upstream <github url>
    $git remote -v
    $ git fetch upstream
    - - if required we can switch upstream and view changes ---
    $ git merge upstream/master
    $ git push origin master # give password if required

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - -

    Source Tree- GIT Client:

    With recent update of Source Tree v 1.9.8 we start seeing problem where it fail to clone with message "warning: templates not found /usr/local/git/share/git-core/templates" on mac osX.

    Following is the solution for this problem:
    1. Got to your home directory. $ cd ~
    2. open .gitconfig in vi (or your comfortable editor).
    3. Add this at beginning of file:
      1. [init]
        templatedir = /Applications/SourceTree.app/Contents/Resources/git_local/share/git-core/templates
    This will resolve the issue, if required restart your Source Tree or machine.

    GIT Hub /or GIT Lab Setting up SSH Keys

    SSH key allows you to establish a secure connection between your computer and GitLab. Before generating an SSH key, check if your system already has one by running cat ~/.ssh/id_rsa.pub If your see a long string starting with ssh-rsa or ssh-dsa, you can skip the ssh-keygen step.

    To generate a new SSH key just open your terminal and use code below. The ssh-keygen command prompts you for a location and filename to store the key pair and for a password. When prompted for the location and filename you can press enter to use the default. It is a best practice to use a password for an SSH key but it is not required and you can skip creating a password by pressing enter. Note that the password you choose here can't be altered or retrieved.

    $ ssh-keygen -t rsa -C "email@gmail.com"

    Use the code below to show your public key.
    cat ~/.ssh/id_rsa.pub
    ------------------------
    ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDncSVBPs0hg5YRZ0NYJHueGpouluJPeKDpHO7gRsFSwUfkjGL5fKg4BCgxJZjdrHQ8G0e9jmt0oXYJpilde5olbrnx5NSEbP1hv18Mq8jTYEd91VH2HsrYJ2TNTgQ79JXA6m1v2UYTd15UwPkhzJEcpP29Cuh/MSX1URBA/aQ3wEfIc6LF45Kyx7St/kiBfPQwJfmcyRsIDv6ly6TQp8GT2nNzWVsFe6JigHN6XKf2YzFXK8oBGJZhv5vBNXYEr86rg7t34E8xYI/yBSGg1k2V+nymEfwhSRbmRyB+zdcvCVKVTSsgg3ySXj89EgDGULc7mfucNnkq0lThLVL1ObyJ email@gmail.com
    ------------------------

    Copy-paste the key to the 'My SSH Keys' section under the 'SSH' tab in your user profile. Please copy the complete key starting with ssh- and ending with your username and host.

    References:

    GIT SCM, About, GitRef, Interactive Git Reference, Git 30 mins Crash Course