Wednesday, April 3, 2013

“Booting AMX” in GlassFish 3 with Groovy

In my previous blog post, I looked at using JMX as one of multiple methods supported by GlassFish 3 for its administration, monitoring, and management. In this blog post, I look in more detail at monitoring and managing GlassFish 3 via JMX and Groovy. I focus on local connection to GlassFish using the Attach API in this post, but I have covered remote JMX access of GlassFish in a previous post (see also Remote Glassfish V3.1 and the mystical JMX settings). The MBeans used for administration are generally the same in either case.

Because I’m using the Attach API in this post’s examples to connect to local Java processes that are started by me, I don’t need to specify the JMX remote connection propertiesjava.rmi.server.hostname,com.sun.management.jmxremote.port, and com.sun.management.jmxremote.ssl=false, and com.sun.management.jmxremote.authenticate) for remote access. The easiest way to find Java processes meeting the standard of being on the local machine and being processes that I started is via use of jps (pre-JDK 7 and JDK 7) or jcmd (JDK 7 only), which I show in the next two screen snapshots.

jpsShowsGlassFishProcessRunningWithPID_1584

jcmdShowsGlassFishProcessRunningWithPID_1584

As the above images indicate, GlassFish is running locally with PID (AKA Process ID or pid) 1584.To begin, I’m going to use Groovy to access the relevant MBeanServerConnection via the Attach API. This is done as shown in the following Groovy code (next two code listings) in which the method retrieveServerConnection(String) accepts the PID and returns the MBeanServerConnection for that Java process. That method uses another method in the code listing, retrieveUrlForPid(String, String), which uses the Attach API to provide a JMXServiceURL for the Java process.

retrieveServerConnection(String)

/** * Provide an MBeanServerConnection based on the provided process ID (pid). * * @param pid Process ID of Java process for which MBeanServerConnection is *    desired. * @return MBeanServerConnection connecting to Java process identified by pid. */def MBeanServerConnection retrieveServerConnection(String pid){   def connectorAddressStr = "com.sun.management.jmxremote.localConnectorAddress"   def jmxUrl = retrieveUrlForPid(pid, connectorAddressStr)   def jmxConnector = JMXConnectorFactory.connect(jmxUrl)   return jmxConnector.getMBeanServerConnection()}

retrieveUrlForPid(String, String)

/** * Provide JMX URL for attaching to the provided process ID (pid). * * @param @pid Process ID for which JMX URL is needed to connect. * @param @connectorAddressStr String for connecting. * @return JMX URL to communicating with Java process identified by pid. */def JMXServiceURL retrieveUrlForPid(String pid, String connectorAddressStr){   // Attach to the target application's virtual machine   def vm = VirtualMachine.attach(pid)   // Obtain Connector Address   def connectorAddress =      vm.getAgentProperties().getProperty(connectorAddressStr)   // Load Agent if no connector address is available   if (connectorAddress == null)   {      def agent = vm.getSystemProperties().getProperty("java.home") +          File.separator + "lib" + File.separator + "management-agent.jar"      vm.loadAgent(agent)      // agent is started, get the connector address      connectorAddress =         vm.getAgentProperties().getProperty(connectorAddressStr)   }   return new JMXServiceURL(connectorAddress);}

With access to the MBeanServerConnection, I can start to do all types of useful things with Groovy and JMX to manage and monitor the a Java process. For example, the next code listing demonstrates how easy it is to now list the MBeans exposed by the Java process identified by a provided PID.

displayHostedMBeans(MBeanServerConnection)

/** * Display MBeans hosted on the provided MBeanServerConnection. * * @param mbeanServer MBeanServerConnection for which hosted MBeans are to be *    provided. */def displayHostedMBeans(MBeanServerConnection mbeanServer){   mbeanServer.queryNames(null, null).each   {      println it   }}

Running the above Groovy method against my running GlassFish instance with PID 1584 is demonstrated in the next screen snapshot.

groovyJmxDisplayHostedMBeansOutputOnGlassFishInstance

displayHostedMBeansAttributesAndOperations(MBeanServerConnection)

/** * Display MBeans hosted on provided MBean Server along with the attributes and * operations available on each MBean. */def displayHostedMBeansAttributesAndOperations(MBeanServerConnection mbeanServer){   mbeanServer.queryNames(null, null).each   { mbeanObjectName ->      def mbeanInfo = mbeanServer.getMBeanInfo(mbeanObjectName)      println mbeanObjectName      println "\tAttributes:"      mbeanInfo.attributes.each      { attribute ->         println "\t\t${attribute.type} ${attribute.name}"      }      println "\tOperations:"      mbeanInfo.operations.each      { operation ->         def operationStr = new StringBuilder();         operationStr << "\t\t" << operation.name << "("         operation.signature.each         { parameter ->            operationStr << parameter.type << " " << parameter.name << ", "         }         def operationString = operationStr.contains(",") ? operationStr.substring(0, operationStr.length()-2) : operationStr         println "${operationString})"      }      println ""   }}

groovyJmxDisplayHostedMBeansOperationsAttributesGlassFishJMX
The previously displayed screen snapshot shows the bootAMX operation available on the amx-support:type=boot-amx MBean. This needs to be run to make other GlassFish-provided AMX MBean available. The next snippet of Groovy code, a method I’ve named bootAmx(MBeanServerConnection), invokes this bootAMX operation to instruct GlassFish to expose significantly more details via its JMX interface.

bootAmx(MBeanServerConnection)

/** * "Boot AMX" on GlassFish. * * @param mbeanServer MBeanServerConnection to be used to invoke bootAMX *    operation. */def bootAmx(MBeanServerConnection mbeanServer){   def amxObjectName = new ObjectName("amx-support:type=boot-amx")   mbeanServer.invoke(amxObjectName, "bootAMX", null, null)}

When the simple Groovy just shown is run, GlassFish exposes significant more functionality via JMX. Now that I’ve “booted AMX,” I can rerun displayHostedMBeans(MBeanServerConnection) to see the new MBeans that are available. A portion of this is shown next in the screen snapshot and the small-font text below it contains the entire output.

groovyJmxDisplayHostedMBeansOutputOnGlassFishInstancePostBootAMX

amx:pp=/domain/configs/config[server-config]/network-config,type=transportsamx:pp=/domain/configs/config[default-config]/iiop-service,type=iiop-listener,name=orb-listener-1amx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ClientProvider],type=property,name=encryption.key.aliasamx:pp=/domain/resources/jdbc-connection-pool[DerbyPool],type=property,name=serverNameamx:pp=/domain/configs/config[default-config]/network-config/protocols/protocol[http-listener-1]/http,type=file-cacheamx:pp=/domain/configs/config[server-config],type=mdb-containeramx:pp=/domain/configs/config[default-config],type=system-property,name=HTTP_LISTENER_PORTamx:pp=/domain/configs/config[server-config]/web-container/session-config/session-manager,type=store-propertiesamx:pp=/ext,type=config-toolsamx:pp=/domain/nodes,type=node,name=localhost-domain1amx:pp=/domain/servers/server[server],type=application-ref,name=__adminguiamx:pp=/domain/configs/config[default-config]/network-config/protocols,type=protocol,name=sec-admin-listeneramx:pp=/J2EEDomain/J2EEServer[server]/WebModule[__admingui],type=Servlet,name=DownloadServlet,j2eeType=Servlet,J2EEServer=server,WebModule=__admingui,J2EEApplication=nullamx:pp=/domain/configs/config[server-config]/network-config/transports,type=transport,name=tcpamx:pp=/domain/configs/config[default-config],type=system-property,name=OSGI_SHELL_TELNET_PORTamx:pp=/domain/configs/config[server-config],type=thread-poolsamx:pp=/domain/configs/config[server-config]/security-service,type=audit-module,name=defaultamx:pp=/domain/secure-admin,type=secure-admin-principal,name="CN=localhost-instance,OU=GlassFish,O=Oracle Corporation,L=Santa Clara,ST=California,C=US"amx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ServerProvider],type=property,name=signature.key.aliasamx:pp=/,type=loggingjava.lang:type=MemoryPool,name=Code Cacheamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[ClientProvider],type=property,name=encryption.key.aliasamx:pp=/domain/configs/config[default-config]/web-container,type=session-configamx:pp=/domain/configs/config[server-config]/security-service/auth-realm[file],type=property,name=fileamx:pp=/domain/configs/config[server-config]/iiop-service,type=iiop-listener,name=SSLamx:pp=/domain/configs/config[server-config]/security-service,type=message-security-config,name=SOAPamx:pp=/domain/configs/config[server-config]/iiop-service/iiop-listener[SSL_MUTUALAUTH],type=sslamx:pp=/domain/configs/config[default-config]/network-config/protocols/protocol[http-listener-1],type=httpamx:pp=/domain/configs/config[default-config]/network-config,type=transportsamx:pp=/domain/configs/config[server-config]/http-service,type=virtual-server,name=serveramx:pp=/domain/configs/config[default-config]/web-container/session-config/session-manager,type=store-propertiesamx:pp=/domain/configs/config[default-config],type=ejb-containeramx:pp=/ext,type=system-statusamx:pp=/domain/configs/config[server-config]/network-config/protocols/protocol[admin-listener],type=httpamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ClientProvider],type=response-policyamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[HttpServlet]/provider-config[GFConsoleAuthModule],type=property,name=loginPageamx:pp=/domain/servers/server[server],type=resource-ref,name=jdbc/__TimerPooljava.lang:type=Memoryamx:pp=/mon/server-mon[server],type=compilation-system-mon,name=jvm/compilation-systemamx:pp=/domain/configs/config[server-config]/security-service,type=auth-realm,name=admin-realmamx:pp=/domain/configs/config[default-config]/log-service,type=module-log-levelsamx:pp=/mon/server-mon[server],type=server-runtime-monamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP],type=provider-config,name=XWS_ClientProvideramx:pp=/domain/configs/config[default-config]/web-container/session-config,type=session-manageramx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP],type=provider-config,name=XWS_ServerProvideramx:pp=/domain/configs/config[server-config]/thread-pools,type=thread-pool,name=http-thread-poolamx:pp=/domain/configs/config[default-config]/admin-service,type=property,name=adminConsoleDownloadLocationamx:pp=/domain/resources/jdbc-connection-pool[DerbyPool],type=property,name=connectionAttributesamx:pp=/domain/resources/jdbc-connection-pool[__TimerPool],type=property,name=connectionAttributesamx:pp=/domain/configs/config[default-config]/network-config/protocols,type=protocol,name=pu-protocolamx:pp=/domain/configs/config[server-config]/network-config,type=protocolsamx:pp=/ext,type=connector-runtime-api-provideramx:pp=/domain,type=resourcesjmxremote:type=jmx-connector-server,protocol=rmi_jrmp,name=systemamx:pp=/domain/configs/config[default-config]/network-config/protocols/protocol[http-listener-2],type=sslamx:pp=/domain/configs/config[default-config]/network-config/protocols/protocol[http-listener-2],type=httpamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[ServerProvider],type=property,name=signature.key.aliasamx:pp=/,type=extamx:pp=/domain/configs/config[default-config]/monitoring-service,type=module-monitoring-levelsamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP],type=provider-config,name=ClientProvideramx:pp=/domain/configs/config[server-config]/security-service/message-security-config[HttpServlet]/provider-config[GFConsoleAuthModule],type=property,name=restAuthURLamx:pp=/domain/configs/config[server-config]/network-config/protocols/protocol[http-listener-1],type=httpamx:pp=/domain/configs/config[server-config]/jms-service,type=jms-host,name=default_JMS_hostamx:pp=/domain/configs/config[server-config]/web-container/session-config/session-manager,type=manager-propertiesamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ServerProvider],type=property,name=debugamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ClientProvider],type=property,name=debugamx:pp=/domain/configs/config[default-config]/network-config/network-listeners,type=network-listener,name=admin-listeneramx:pp=/domain/configs/config[default-config]/security-service/jacc-provider[default],type=property,name=repositoryamx:pp=/mon/server-mon[server],type=operating-system-mon,name=jvm/operating-systemamx:pp=/domain/configs/config[default-config]/security-service,type=audit-module,name=defaultjava.lang:type=MemoryPool,name=Survivor Spaceamx:pp=/domain/configs/config[default-config]/network-config,type=protocolsamx:pp=/domain/configs/config[server-config]/network-config/protocols/protocol[http-listener-2],type=sslamx:pp=/domain/configs/config[default-config]/thread-pools,type=thread-pool,name=http-thread-poolamx:pp=/J2EEDomain/J2EEServer[server]/WebModule[__admingui],type=Servlet,name=jsp,j2eeType=Servlet,J2EEServer=server,WebModule=__admingui,J2EEApplication=nullamx:pp=/domain/configs/config[default-config]/network-config/protocols/protocol[pu-protocol],type=port-unificationamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[ClientProvider],type=property,name=security.configamx:pp=/domain/configs/config[default-config],type=system-property,name=HTTP_SSL_LISTENER_PORTamx:pp=/domain/configs/config[default-config]/http-service,type=virtual-server,name=serveramx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ClientProvider],type=request-policyamx:pp=/domain/configs/config[server-config],type=iiop-serviceamx:pp=/domain/configs/config[default-config]/security-service,type=jacc-provider,name=defaultamx:pp=/domain/configs/config[default-config]/web-container/session-config/session-manager,type=manager-propertiesamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ClientProvider],type=request-policyamx:pp=/domain/configs/config[default-config]/security-service,type=auth-realm,name=certificatejava.nio:type=BufferPool,name=mappedjava.lang:type=Compilationamx:pp=/,type=runtimeamx:pp=/domain/configs/config[server-config]/monitoring-service,type=module-monitoring-levelsamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[ClientProvider],type=property,name=dynamic.username.passwordamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[ClientProvider],type=property,name=signature.key.aliasamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ClientProvider],type=property,name=encryption.key.aliasamx-support:type=amx-loader,name=configamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[ClientProvider],type=property,name=dynamic.username.passwordamx:pp=/runtime,type=server-runtime,name=serveramx:pp=/domain/configs/config[server-config]/network-config/protocols,type=protocol,name=http-listener-1amx:pp=/domain,type=system-applicationsamx:pp=/domain/configs/config[server-config]/security-service,type=jacc-provider,name=defaultamx:pp=/J2EEDomain/J2EEServer[server]/JDBCResource[jdbc/__default]/JDBCDataSource[jdbc/__default],type=JDBCDriver,name=jdbc/__default,j2eeType=JDBCDriver,J2EEServer=server,JDBCResource=jdbc/__default,JDBCDataSource=jdbc/__defaultamx:pp=/domain/configs/config[server-config]/security-service/auth-realm[file],type=property,name=jaas-contextamx:pp=/domain/configs/config[server-config]/ejb-container,type=ejb-timer-serviceamx:pp=/domain/configs/config[default-config]/security-service,type=auth-realm,name=filejava.lang:type=Runtimeamx:pp=/J2EEDomain/J2EEServer[server]/WebModule[__admingui],type=Servlet,name=default,j2eeType=Servlet,J2EEServer=server,WebModule=__admingui,J2EEApplication=nullamx:pp=/domain/configs/config[default-config],type=web-containeramx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[ClientProvider],type=property,name=debugamx:pp=/domain/system-applications/application[__admingui]/module[__admingui],type=engine,name=securityamx:pp=/domain/configs/config[server-config]/admin-service,type=jmx-connector,name=systemamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ServerProvider],type=response-policyamx:pp=/ext,type=realmsamx:pp=/,type=queryamx:pp=/domain/configs/config[default-config],type=thread-poolsamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[HttpServlet]/provider-config[GFConsoleAuthModule],type=property,name=loginErrorPageamx:pp=/domain/configs/config[server-config],type=connector-serviceamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[ServerProvider],type=property,name=signature.key.aliasamx:pp=/domain/configs/config[default-config]/network-config,type=network-listenersamx:pp=/J2EEDomain/J2EEServer[server]/JDBCResource[jdbc/__TimerPool]/JDBCDataSource[jdbc/__TimerPool],type=JDBCDriver,name=jdbc/__TimerPool,j2eeType=JDBCDriver,J2EEServer=server,JDBCResource=jdbc/__TimerPool,JDBCDataSource=jdbc/__TimerPoolamx:pp=/domain/configs/config[default-config],type=system-property,name=JMS_PROVIDER_PORTamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ServerProvider],type=request-policyamx:pp=/domain/configs/config[default-config],type=availability-serviceamx:pp=/domain/configs/config[default-config]/network-config/protocols/protocol[admin-http-redirect],type=http-redirectamx:pp=/,type=J2EEDomain,j2eeType=J2EEDomain,name=amxamx:pp=/domain/configs/config[default-config],type=system-property,name=IIOP_SSL_LISTENER_PORTamx:pp=/domain/configs/config[default-config]/iiop-service,type=iiop-listener,name=SSLamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[ServerProvider],type=property,name=encryption.key.aliasamx:pp=/domain/configs/config[default-config]/network-config/transports,type=transport,name=tcpamx:pp=/domain/configs/config[default-config],type=system-property,name=JMX_SYSTEM_CONNECTOR_PORTamx:pp=/mon/server-mon[server],type=garbage-collector-mon,name=jvm/garbage-collectors/Copyamx:pp=/domain/configs/config[default-config]/http-service,type=virtual-server,name=__asadminamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[ClientProvider],type=request-policyamx:pp=/,type=system-infoamx:pp=/domain/configs/config[default-config],type=group-management-serviceamx:pp=/domain/configs/config[default-config]/availability-service,type=web-container-availabilityamx:pp=/domain/configs/config[server-config]/group-management-service,type=failure-detectionamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[ClientProvider],type=response-policyjava.lang:type=GarbageCollector,name=Copyamx:pp=/domain/configs/config[server-config],type=java-configamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP],type=provider-config,name=ServerProvideramx:pp=/domain/configs/config[default-config]/network-config/protocols/protocol[http-listener-2]/http,type=file-cacheamx:pp=/domain/configs/config[default-config],type=system-property,name=ASADMIN_LISTENER_PORTamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[ServerProvider],type=request-policyamx:pp=/domain/configs/config[server-config]/network-config/protocols,type=protocol,name=http-listener-2amx:pp=/domain/configs/config[default-config]/jms-service,type=jms-host,name=default_JMS_hostamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[ClientProvider],type=property,name=debugamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP],type=provider-config,name=ServerProvideramx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ClientProvider],type=property,name=signature.key.aliasamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[ServerProvider],type=response-policyamx:pp=/domain/configs/config[server-config],type=web-containeramx:pp=/domain/configs/config[default-config]/security-service/auth-realm[admin-realm],type=property,name=jaas-contextjava.util.logging:type=Loggingamx:pp=/,type=toolsjava.lang:type=MemoryPool,name=Eden Spaceamx:pp=/domain/configs/config[default-config]/network-config/protocols,type=protocol,name=http-listener-2com.sun.management:type=HotSpotDiagnosticamx:pp=/domain/configs/config[default-config]/security-service,type=jacc-provider,name=simpleamx:pp=/domain/configs/config[default-config]/security-service,type=auth-realm,name=admin-realmamx:pp=/J2EEDomain/J2EEServer[server]/WebModule[__admingui],type=Servlet,name=FacesServlet,j2eeType=Servlet,J2EEServer=server,WebModule=__admingui,J2EEApplication=nullamx:pp=/domain/configs/config[server-config]/admin-service,type=property,name=adminConsoleContextRootamx:pp=/domain/configs/config[default-config],type=monitoring-serviceamx:pp=/domain/configs/config[server-config]/security-service,type=auth-realm,name=fileamx:pp=/domain/configs/config[server-config]/security-service/auth-realm[admin-realm],type=property,name=jaas-contextamx:pp=/domain/configs/config[server-config]/security-service/audit-module[default],type=property,name=auditOnamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[ClientProvider],type=response-policyamx:pp=/domain/configs/config[default-config]/security-service/auth-realm[file],type=property,name=jaas-contextamx:pp=/domain/system-applications,type=application,name=__adminguiamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[ServerProvider],type=property,name=security.configamx:pp=/domain/configs/config[default-config]/iiop-service/iiop-listener[SSL],type=sslamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ClientProvider],type=property,name=signature.key.aliasamx:pp=/domain/configs/config[default-config],type=connector-serviceamx:pp=/domain/configs/config[server-config],type=ejb-containeramx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[ServerProvider],type=request-policyamx:pp=/mon/server-mon[server],type=garbage-collector-mon,name=jvm/garbage-collectors/MarkSweepCompactamx:pp=/domain/configs/config[default-config]/security-service/audit-module[default],type=property,name=auditOnamx:pp=/domain,type=secure-adminamx:pp=/domain/configs/config[default-config]/network-config/protocols,type=protocol,name=http-listener-1amx:pp=/,type=sampleamx:pp=/domain/configs/config[default-config]/group-management-service,type=failure-detectionamx:pp=/domain/configs/config[default-config]/network-config/network-listeners,type=network-listener,name=http-listener-1amx:pp=/domain/system-applications/application[__admingui],type=module,name=__adminguiamx:pp=/J2EEDomain/J2EEServer[server]/WebModule[__admingui],type=Servlet,name=ThemeServlet,j2eeType=Servlet,J2EEServer=server,WebModule=__admingui,J2EEApplication=nullamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ServerProvider],type=request-policyamx:pp=/domain/configs,type=config,name=default-configamx:pp=/domain/system-applications/application[__admingui]/module[__admingui],type=engine,name=webamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ClientProvider],type=property,name=dynamic.username.passwordamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[ClientProvider],type=property,name=security.configjava.nio:type=BufferPool,name=directamx:pp=/domain/configs/config[server-config]/network-config/network-listeners,type=network-listener,name=http-listener-2amx:pp=/domain/configs/config[server-config]/iiop-service,type=orbamx:pp=/domain/configs/config[default-config],type=java-configamx:pp=/domain,type=property,name=administrative.domain.nameamx:pp=/domain,type=load-balancersamx:pp=/domain/resources/jdbc-connection-pool[__TimerPool],type=property,name=databaseNameamx:pp=/domain/resources,type=jdbc-connection-pool,name=DerbyPoolamx:pp=/domain/configs/config[default-config]/thread-pools,type=thread-pool,name=thread-pool-1amx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ServerProvider],type=property,name=encryption.key.aliasamx:pp=/domain/configs/config[default-config],type=diagnostic-serviceamx:pp=/domain/configs/config[default-config],type=security-serviceamx:pp=/domain/configs/config[default-config],type=system-property,name=IIOP_LISTENER_PORTamx:pp=/J2EEDomain/J2EEServer[server]/JDBCResource[jdbc/__TimerPool],type=JDBCDataSource,name=jdbc/__TimerPool,j2eeType=JDBCDataSource,J2EEServer=server,JDBCResource=jdbc/__TimerPoolamx:pp=/domain/resources/jdbc-connection-pool[DerbyPool],type=property,name=PortNumberamx:pp=/domain/configs/config[server-config],type=admin-serviceamx:pp=/domain/resources/jdbc-connection-pool[DerbyPool],type=property,name=DatabaseNameamx:pp=/domain/configs/config[default-config]/network-config/protocols/protocol[admin-listener]/http,type=file-cacheamx:pp=/domain/configs/config[server-config]/web-container/session-config,type=session-managerjava.lang:type=MemoryPool,name=Tenured Genamx:pp=/domain/configs/config[server-config]/thread-pools,type=thread-pool,name=admin-thread-poolamx:pp=/domain/configs/config[server-config]/security-service,type=jacc-provider,name=simpleamx:pp=/domain/configs/config[server-config],type=monitoring-serviceamx:pp=/domain/configs/config[server-config]/security-service,type=property,name=default-digest-algorithmamx:pp=/domain/configs/config[default-config],type=network-configamx:pp=/,type=monamx:pp=/domain/configs/config[default-config],type=mdb-containeramx-support:type=boot-amxamx:pp=/domain/configs/config[default-config],type=transaction-serviceamx:pp=/J2EEDomain/J2EEServer[server],type=JDBCResource,name=jdbc/__default,j2eeType=JDBCResource,J2EEServer=serveramx:pp=/domain/configs/config[server-config]/network-config/protocols/protocol[admin-listener]/http,type=file-cacheamx:pp=/domain/configs/config[default-config]/network-config/protocols/protocol[admin-listener],type=httpamx:pp=/domain,type=serversamx:pp=/domain/configs/config[default-config]/network-config/protocols,type=protocol,name=admin-http-redirectamx:pp=/domain/servers,type=server,name=serveramx:pp=/domain/configs/config[default-config]/availability-service,type=ejb-container-availabilityamx:pp=/domain/configs/config[server-config]/admin-service,type=property,name=ipsRootamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ServerProvider],type=response-policyamx:pp=/domain/configs/config[server-config]/iiop-service,type=iiop-listener,name=orb-listener-1java.lang:type=GarbageCollector,name=MarkSweepCompactamx:pp=/domain/configs/config[server-config]/admin-service,type=das-configamx:pp=/mon/server-mon[server],type=thread-system-mon,name=jvm/thread-systemamx:pp=/domain/resources,type=jdbc-resource,name=jdbc/__TimerPoolamx:pp=/J2EEDomain/J2EEServer[server]/JDBCResource[jdbc/__default],type=JDBCDataSource,name=jdbc/__default,j2eeType=JDBCDataSource,J2EEServer=server,JDBCResource=jdbc/__defaultamx:pp=/domain/configs/config[server-config]/security-service/jacc-provider[default],type=property,name=repositoryamx:pp=/domain/configs/config[server-config]/http-service,type=access-logjava.lang:type=ClassLoadingamx:pp=/domain/configs/config[server-config]/network-config/protocols,type=protocol,name=admin-listenerjava.lang:type=Threadingamx-support:type=amx-loader,name=j2eeamx:pp=/domain/configs/config[server-config]/security-service/auth-realm[admin-realm],type=property,name=fileamx:pp=/mon/server-mon[server],type=memory-mon,name=jvm/memoryamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[ServerProvider],type=property,name=debugamx:pp=/domain/configs/config[default-config]/network-config/protocols,type=protocol,name=admin-listeneramx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ClientProvider],type=property,name=debugamx:pp=/domain/configs/config[server-config]/security-service,type=message-security-config,name=HttpServletamx:pp=/domain/configs/config[server-config]/web-container,type=session-configamx:pp=/domain/resources/jdbc-connection-pool[DerbyPool],type=property,name=Useramx:pp=/domain/configs/config[server-config]/thread-pools,type=thread-pool,name=thread-pool-1amx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[ServerProvider],type=property,name=encryption.key.aliasamx:pp=/domain/configs/config[default-config]/http-service,type=access-logamx:pp=/mon,type=server-mon,name=serveramx:pp=/domain/servers/server[server],type=resource-ref,name=jdbc/__defaultamx:pp=/domain/configs/config[default-config],type=http-serviceamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[ClientProvider],type=property,name=signature.key.aliasamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ClientProvider],type=property,name=dynamic.username.passwordamx:pp=/domain/resources/jdbc-connection-pool[DerbyPool],type=property,name=Passwordamx:pp=/domain/configs/config[default-config]/network-config/protocols/protocol[pu-protocol]/port-unification,type=protocol-finder,name=admin-http-redirectamx:pp=/domain/configs/config[default-config]/security-service/auth-realm[file],type=property,name=fileamx:pp=/domain/configs/config[default-config]/security-service/auth-realm[admin-realm],type=property,name=fileamx:pp=/domain/configs/config[default-config]/iiop-service,type=orbamx:pp=/domain/configs/config[default-config]/admin-service,type=das-configamx:pp=/domain/configs,type=config,name=server-configamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[HttpServlet]/provider-config[GFConsoleAuthModule],type=request-policyamx:pp=/domain/configs/config[default-config],type=log-serviceamx:pp=/domain/configs/config[default-config]/iiop-service,type=iiop-listener,name=SSL_MUTUALAUTHamx:pp=/domain/configs/config[default-config],type=iiop-serviceamx:pp=/domain/configs/config[server-config]/iiop-service,type=iiop-listener,name=SSL_MUTUALAUTHamx:pp=/domain/configs/config[server-config]/security-service,type=auth-realm,name=certificateamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP],type=provider-config,name=ClientProvideramx:pp=/domain/configs/config[server-config],type=security-serviceamx:pp=/domain/configs/config[default-config]/security-service,type=message-security-config,name=SOAPamx:pp=/mon/server-mon[server],type=runtime-mon,name=jvm/runtimeamx:pp=/domain,type=lb-configsamx:pp=/J2EEDomain/J2EEServer[server],type=WebModule,name=__admingui,j2eeType=WebModule,J2EEServer=server,J2EEApplication=nulljava.lang:type=MemoryPool,name=Perm Genamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[HttpServlet],type=provider-config,name=GFConsoleAuthModuleamx:pp=/mon/server-mon[server],type=class-loading-system-mon,name=jvm/class-loading-systemjava.lang:type=MemoryManager,name=CodeCacheManageramx:pp=/domain/resources,type=jdbc-resource,name=jdbc/__defaultamx-support:type=mbean-trackeramx:pp=/domain/configs/config[server-config],type=network-configamx:pp=/domain/configs/config[server-config]/network-config/protocols/protocol[http-listener-2],type=httpamx:pp=/domain,type=configsamx:pp=/domain/configs/config[server-config]/http-service,type=virtual-server,name=__asadminamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP],type=provider-config,name=XWS_ClientProvideramx:pp=/domain/configs/config[default-config]/web-container/session-config,type=session-propertiesamx-support:type=amx-loader,name=startupamx:pp=/domain/configs/config[default-config],type=admin-serviceamx:pp=/domain/configs/config[default-config]/network-config/network-listeners,type=network-listener,name=http-listener-2amx:pp=/domain/configs/config[server-config],type=jms-serviceamx:pp=/domain/configs/config[default-config]/network-config/protocols/protocol[sec-admin-listener]/http,type=file-cacheamx:pp=/domain/configs/config[default-config]/network-config/protocols/protocol[sec-admin-listener],type=sslamx:pp=/domain,type=clustersamx:pp=/domain,type=nodesamx:pp=/domain/configs/config[default-config]/thread-pools,type=thread-pool,name=admin-thread-poolamx-support:type=AMXConfigLoaderamx:pp=/domain/configs/config[default-config]/ejb-container,type=ejb-timer-serviceamx:pp=/domain/configs/config[default-config]/iiop-service/iiop-listener[SSL_MUTUALAUTH],type=sslamx:pp=/domain/configs/config[server-config]/network-config/protocols/protocol[http-listener-2]/http,type=file-cacheamx:pp=/domain/resources,type=jdbc-connection-pool,name=__TimerPoolamx:pp=/domain/configs/config[default-config],type=jms-serviceamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[ClientProvider],type=request-policyamx:pp=/domain/configs/config[server-config]/network-config/network-listeners,type=network-listener,name=admin-listeneramx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ServerProvider],type=property,name=debugamx:pp=/domain/configs/config[default-config],type=system-property,name=JAVA_DEBUGGER_PORTamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ServerProvider],type=property,name=encryption.key.aliasamx:pp=/domain/configs/config[server-config]/network-config,type=network-listenersamx:pp=/domain/secure-admin,type=secure-admin-principal,name="CN=localhost,OU=GlassFish,O=Oracle Corporation,L=Santa Clara,ST=California,C=US"amx:pp=/domain/configs/config[server-config]/network-config/network-listeners,type=network-listener,name=http-listener-1amx:pp=/domain/configs/config[server-config]/web-container/session-config,type=session-propertiesamx:pp=/,type=bulk-accessamx:pp=/domain/configs/config[server-config],type=group-management-serviceamx:pp=/domain/configs/config[default-config],type=management-rulesamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ServerProvider],type=property,name=signature.key.aliasamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[XWS_ClientProvider],type=response-policyamx:pp=/domain/configs/config[default-config]/availability-service,type=jms-availabilityamx:pp=/domain/configs/config[default-config]/admin-service,type=jmx-connector,name=systemamx:pp=/domain/configs/config[default-config]/http-service/virtual-server[server],type=property,name=default-web-xmlamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[ServerProvider],type=response-policyamx:pp=/domain/configs/config[server-config]/network-config/protocols/protocol[http-listener-1]/http,type=file-cacheamx:pp=/domain/configs/config[server-config]/admin-service,type=property,name=adminConsoleDownloadLocationamx:pp=/domain/configs/config[default-config]/network-config/protocols/protocol[sec-admin-listener],type=httpamx:pp=/domain/configs/config[server-config],type=transaction-servicejava.lang:type=OperatingSystemamx:pp=/J2EEDomain/J2EEServer[server],type=JVM,j2eeType=JVM,J2EEServer=serveramx:pp=/,type=pathnamesamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP]/provider-config[ServerProvider],type=property,name=security.configamx-support:type=amx-loader,name=extamx:pp=/domain/configs/config[server-config]/security-service/message-security-config[SOAP],type=provider-config,name=XWS_ServerProvideramx:pp=/domain/configs/config[server-config]/security-service/message-security-config[HttpServlet]/provider-config[GFConsoleAuthModule],type=response-policyamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[ServerProvider],type=property,name=debugamx:pp=/domain/configs/config[default-config]/network-config/protocols/protocol[pu-protocol]/port-unification,type=protocol-finder,name=http-finderamx:pp=/J2EEDomain/J2EEServer[server],type=JDBCResource,name=jdbc/__TimerPool,j2eeType=JDBCResource,J2EEServer=serveramx:pp=/domain/configs/config[server-config],type=http-serviceamx:pp=/,type=domainamx:pp=/domain/configs/config[default-config]/security-service/message-security-config[SOAP]/provider-config[ClientProvider],type=property,name=encryption.key.aliasamx:pp=/domain,type=applicationsamx:pp=/domain/configs/config[default-config],type=system-property,name=IIOP_SSL_MUTUALAUTH_PORTamx:pp=/domain/configs/config[server-config]/iiop-service/iiop-listener[SSL],type=sslamx:pp=/J2EEDomain,type=J2EEServer,name=server,j2eeType=J2EEServeramx:pp=,type=domain-rootJMImplementation:type=MBeanServerDelegate

As this image and the small-font text demonstrate, “booting AMX” has led to GlassFish exposing significant monitoring and management capabilities via JMX.

Conclusion

This post has demonstrated using Groovy to explore the standard JMX MBeans provided by the Java Platform as well as the AMX beans that GlassFish provides. The last Groovy code snippet invokes GlassFish’s “bootAMX” operation to unleash significantly more GlassFish JMX-based monitoring and managing capabilities. Although all of this could be accomplished with a GUI-based JMX client such as JConsole or JVisualVM, there are advantages at times to running things in scripts. Using Groovy as demonstrated in this post allows scripts to easily interact with GlassFish for administration.
 

Reference: “Booting AMX” in GlassFish 3 with Groovy from our JCG partner Dustin Marx at the Inspired by Actual Events blog.


Source : feedproxy[dot]google[dot]com

Working with Amazon Web Services (EC2)

As posted before I attended to a technical handson AWS training last week. The subjects during these days were of course the standard EC2 and S3 services which I have used before. Added to that we worked with RDS, Elastic Load Balancing, SNS and VPC, Elastic Beanstalk and discussed a lot of terminology and business cases. In this post I setup a new EC2 server and connect to it with your MacOs although it will work similar in case of Linux. I have an account at AWS in place. Before you start make sure you have selected the correct region (for a simple demo it isn’t very big thing but when you are going to setup a real server it can make a big difference in the costs (network traffic) and latency although there are solutions for that). By the way, there are two approaches to setup your EC2 server, you can choose a “S3 backed” AMI (Amazon Machine Image) or a “EBS-bakced” AMI. There are a lot of good articles
 
available about the differences and when to use which one. In this demo I will install a “pre-baked” AMI with a complete WordPress setup installed. There are thousands of these AMI’s available in the AWS community. For this one launch the AWS Management Console at http://aws.amazon.com and choose the EC2 tab. In the AWS console make certain you selected the correct region and select ‘Images-AMIs’ in the left menu and search for “bitnami-wordpress”:

Screen Shot 2012-12-09 at 08.05.04

Select the AMI of your choice (I have 64-bit Ubuntu running WordPress 3.4.2.1) and click ‘Launch’. Now simply follow the steps of the wizard (although there is a lot to tell about almost every option in the wizard I simply go for the most default installation). At the Instance Details step make sure you select a Micro instance (to cut down the cost of having this demo running):

Screen Shot 2012-12-09 at 08.15.57

In the next two steps simply accept all defaults:

Screen Shot 2012-12-09 at 08.16.47

Screen Shot 2012-12-09 at 08.17.12

At the Create Key Pair step create a key pair if you haven’t already done so:

Screen Shot 2012-12-09 at 08.19.19

The next step Configure Firewall create a Security Group so we are able to access our Linux instance from the outside world by HTTP and SSH:

Screen Shot 2012-12-09 at 08.21.36

Finally review all your settings and if it is okay then launch the instance:

Screen Shot 2012-12-09 at 08.22.31

After a few seconds you should be able to see your new instance in the Instances overview in the AWS Management Console:

Screen Shot 2012-12-09 at 08.29.57

Please pay specific attention to the public DNS that is assigned to the instance. As you might be aware this DNS will change after you stopped and started this instance. So I use it now to show how to connect to the instance via SSH but you should not use this DNS as if it was a fixed IP/DNS. To work around this issue Amazon supplies Elastic IP which I show in another post.

To connect with SSH to this instance open up a Terminal on your Mac and type the following commands. First I had to narrow the permissions on the downloaded pem file for which I used: chmod u=r,go= 4synergy_palma.pem Then I was able to connect to the Bitnami instance via SSH with: ssh -i 4synergy_palma.pem bitnami@ec2-54-246-78-211.eu-west-1.compute.amazonaws.com as you can see here:

Screen Shot 2012-12-09 at 09.08.39

And of course we can enter our WordPress by opening the home URL in a web browser:

Screen Shot 2012-12-09 at 09.15.20
 

Reference: Working with Amazon Web Services (EC2) from our JCG partner Pascal Alma at the The Pragmatic Integrator blog.


Source : feedproxy[dot]google[dot]com

Evaluating new frameworks, libraries and technologies

Introduction

New frameworks and libraries are developed so fast it is nearly impossible to evaluate all of them. This can make it hard to judge whether a particular technology is worth investing (time) in. This post gives you some tips which may help when evaluating new technology.

Conceptual level

Although there are many different libraries and frameworks, most of them can be grouped based on some conceptual differentiation. The following concepts may help to
 
give an idea of this conceptual differentiation:

  • Component based frameworks
  • Request/response based frameworks
  • Object Relational Mapping
  • Map-reduce
  • Key-value stores
  • Messaging
  • And many more…

When evaluating a specific technology it helps to identify to which concept or concepts it belongs. Before further analysis of a particular technology, make sure you understand the concepts. Without this understanding it is almost impossible to do an objective analysis. Understanding these concepts requires an investment in time. Usually in the form of reading, watching presentations, experimenting, training and talking to others. Understanding the concepts will make it easier to objectively evaluate a particular technology.

Simpler is usually better

One of the key actions in evaluating a particular technology is to determine if and how it satisfies the given requirements. A lot of frameworks and libraries provide a 1 minute introduction, a 5 minute guide, a 30 minute tutorial and more. I really like these sorts of introductions since it usually gets you up-to-speed quickly. Besides getting up-to-speed quickly, a more important factor is the complexity of the given solution. I really like the idea of ‘Make things as simple as possible, but not simpler’.

The starter guides, as mentioned above, present the readers with a relatively simple case or problem to demonstrate the key features of a given technology. To find out if a certain technology will fit I suggest to look at the complexity of the solution for the cases in the introduction guides.

In my opinion, if the solution for a relatively simple case or problem is complex and not easy to understand, how can a solution to a more complex problem be easy to understand? This complexity comes of course in various flavours:

  • How much code do I need to write to get even the simplest things done?
  • How many classes do I need to extend?
  • What and how much configuration should I write?
  • What is the quality of the documentation?
  • How can I easily test my solution?
  • Etc.

If the solution to a simple problem is indeed simple and easy to understand, it is worth investigating more time to find out if the technology satisfies your requirements. If the solution to a simple problem is not simple and not easy to understand, think long and hard before investing more time in it.

Conclusion

New frameworks and libraries are developed so fast it is nearly impossible to evaluate all of them. To speed up the decision process make sure you understand the technology at the conceptual level. Once you understand the conceptual level, experiment with the technology using introduction guides if they are available. If, from those introduction guides, solutions to a given problem are simple and easy to understand, it may be well worth spending more time investigating the particular technology for more complex problems. If not, proceed with care.
 

Reference: Evaluating new frameworks, libraries and technologies from our JCG partner Jamie Craane at the Jamie Craane’s Blog blog.


Source : feedproxy[dot]google[dot]com

Tuesday, April 2, 2013

Spring Integration – Apache Camel comparison

A year after v2.1 had been released, Spring Integration v2.2 is out with 3 new components MondoDB, Redis and JPA (even though the first 2 were listed also in v2.1 as message store, now they are available as Inbound and Outbound Channel Adapters), retry and other new features. As a comparison Apache Camel has also released v2.10 during the same period with around 18 new components. JPA support in Camel is available from long time, MongoDB since v2.10 and Redis since my commit couple of days ago. But of course the number of connectors (more than 130 for Camel) is not the most important characteristic for an integration framework (some might argue that). There are many other factors which matter when choosing an open source project for your needs. A quick search on the internet will show you which are the main questions you should ask before deciding which open source project to use
 
for your enterprise. Here are only couple of them and my biased answers:

1. What is the license? – Apache Camel (like all Apache projects) and Spring Integration both are using Apache License version 2.0 which is one of the most permissive licences. It basically says do whatever you want with the software.

2. Is the project actively developed? – According to ohloh.net for the last 12 months Apache Camel has 2415 commits from 24 committers whereas Spring Integration has 949 commits from 17 committers.

3. How mature is the project? – Both projects have started in 2007 and currently Spring Integration has 234K lines of code and is estimated to 60 years of effort, whereas Apache Camel has 800K lines of code and estimated to 220 years of effort.

4. How big and responsive is the community? – If you are creating a project different than ‘Hello World’, no matter how many books and tutorials there are, sooner or later you will have questions. And this is another area where Camel shines. According to Apache stats, Camel users and developers lists have around 700 subscribers combined who send 45 messages per day in total on average. If you ask a question, the chances are, you will get a response in a matter of minutes. On Spring Integration forums there are 24,355 messages since the start of the project, which on average means 13 messages a day.

Jira stats for last 30 days


5. How long it takes to fix a bug? – Personally for me this is a very important metric about open source projects. Imagine you found a bug in the project, a small bug that makes your day miserable. Then you go the extra mile to fix it, prove it with tests, submit a patch, describe it on the project forum/mailing list, but it never gets reviewed or included in the next release… Looking at the reported/resolved issues ratio for the last 30 days, as of mid January, Camel has resolved 80 out of 90 reported issues, whereas SI resolved 3 out of 19. But I strongly believe this is due to recent holiday season and the graph below will look better for SI later in the year.

6. How good is the documentation? – Both projects have quite extensive documentation, tutorials and plenty of blog posts. There are 3 books published covering Spring Integration – having read all of them, I can say more or less they talk about EIPs and repeat Spring Integration documentation but with better graphics. Camel for now has only one book published – Camel in Action by Claus Ibsen and Jonathan Anstey. There are aslo plenty of blog posts, tutorials and webinars for both projects out there. There is one thing that Spring Integration is missing though – CamelOne conference

7. Is there good tool support? – SpringSource develops Eclipse based Spring Tool Suite(STS) which has visual development tools for SI. IntelliJ IDEA also has SI support, but that is limitted to autocompliting varios endpoint options.

Spring Tool Suite


The most popular tool for developing Camel routes is Fuse IDE from FuseSource, which is also Eclipse based tool. There is also another Eclipse based graphical tool for Camel – Talend ESB

Fuse IDE


8. Can I get a commercial support if I need it? – If you have more money than time, both projects have companies offering commercial support. This is useful when you don’t have much time to spent for asking questions on the mailing lists or browsing the source code. There are also plenty of independent consultants you can reach through the mailing lists. These are only some of the questions you should ask yourself before adding one or the other dependency to your product. The more specific questions you should ask depends on your product portfolio, project stack, team abilities and motivation to learn new technologies.

Disclaimer: I’m Apache Camel committer and I absolutely adore Camel. I’ve also worked on projects where we chose Spring Integration over Apache Camel.
 

Reference: Spring Integration – Apache Camel comparison from our JCG partner Bilgin Ibryam at the OFBIZian blog.


Source : feedproxy[dot]google[dot]com

Telecommuting, Hoteling, and Managing Product Development

There are two sides of this conversation about telecommuting: the employee side and the management side. I hope you stick around for both sides. You can yell at me at the end.

Employees: You Owe the Company a Full Day of Work

I’ve been thinking since Marissa Meyer’s announcement what I would say about the end of telecommuting at Yahoo!. Best Buy employees now have to have a conversation with their managers about how they will manage their telecommuting.

People who work remotely full-time have an obligation to their team-mates to be
 
available, to make it easy for their team to find them. Once you have a telecommuter, you have a geographically distributed team, and anyone who’s been on one, knows the stresses that places on a team. It’s not impossible. It’s just harder on everyone.

I know the Bay Area has horrible traffic. I know the problems of being a parent and commuting to work. Mark and I managed those problems for more than 20 years, until our children graduated from high school. (Just because your children can drive does not mean you don’t worry about them. If they have mono in high school, you still worry about them. Yes, you do.)

And, I will tell you this: If you are camped out in the dining room or the living room on your computer and the kids are running around, or if you are driving the kids to their activities, you might be doing email, or you might be on the phone, but your work is not 100% on work. You are not focused. You cannot possibly be giving 100% of your brain to work. Some part of your brain is wondering what the kids are doing. Or, wondering why the kids got so quiet. Or, wondering why you can’t hear the dog anymore. This is not a full day of work.

If you work from home on a regular basis, and you regularly work from the dining room, I’ll say the truth: you are shortchanging the company. You are not delivering a full day of work.

Staying home when a child has a fever? Of course, you must. Staying home when a child has the mumps or measles or chickenpox? (Does anyone get these diseases now?) You must. You and your spouse can discuss/fight over who has to take time off. We did. You can, too. Good luck. That’s a marriage/career issue. I’m not getting into the middle of that one.

But the cost to the team of you not working with the team on a daily basis? That is so high. If you want to know, measure the value stream in your project.

Anyone can make telecommuting work. Especially if it’s just one or two days a week. But five days a week? No. That’s not reasonable for your teams. And, I wonder why you chose that. I bet some of you chose that because your company did not provide a reasonable environment for you.

Telecommute in an emergency? Of course. On a regular basis? Especially if you want agile teams? Craziness.

Once you have established teams, teams can create their own norms. But it takes many iterations and lots of trust to build those established norms.

Companies, You Owe Employes a Reasonable Work Environment

Once we get past the emergency days when parents must take time off from work, and have people back at work, what will we do with these people? We need reasonable work environments. Here’s what constitutes reasonable for me:

  • A team room for an agile team
  • Rooms for cross-functional teams to meet. (Even if you are not agile, you need rooms for cross-functional teams to meet. Yes, you do.)
  • An “office” for each person. It can be small if there is a team room.
  • Sufficient meeting space, so you do not have to go to buildings half a mile away for a meeting. Companies: Measure the time wasted trying to find a meeting room!
  • Enough bathrooms, so people like me don’t have to go to the men’s room, and shout “Woman incoming, there is no woman’s room on this floor.” (Don’t think I’m kidding. I’m not.)
  • Enough parking, close enough so people don’t have to wonder how long it will take them drive home, after they’ve hiked to their car
  • Lighted parking lots. Keep it safe, please.

There is more. That is the minimum. Think coffee, water, that kind of thing.

You know what’s missing from that list? The stupid “hotel” idea that companies thought they could get away with. “We don’t need a place for employees. They’ll plug in wherever they are, and that will be their place for the day.” The hoteling idea is total nonsense.

Well, that’s a way to make people feel as if they are welcomed, and part of a team. Not! This blog is called “Managing Product Development” for a reason. If you want to release products, you need teams. If you want teams of people to organize in some way, they need to know where to congregate. How the heck can they know where to congregate, if they have no place to sit?

“Hoteling” employees has to be just about the most stupid idea I ever heard. I don’t know who dreamed it up. Probably some architect who has a lovely office to sit in. Or an executive who has a permanent desk.

People need to know they are wanted. Do you want your employees? Give each of them a permanent space.

Oh, and don’t talk to me about introverts. Highly introverted people, who prefer to not talk to people, want to know where they will sit. They just don’t want to talk to more than one person while they sit there. Okay, some of them don’t even want to talk to one person, but they want a place to sit.

What Do You Need for Your Product Development?

Can you make telecommuting work for your organization? Of course you can. You can make geographically distributed teams work. I have a workshop on it, and I just published a paper on it. You are a smart person, working with smart people. The question is this: What will make your product development proceed faster, with more ease, with less cost, and allow you the most flexibility?

One of the reasons I urge my clients to transition to agile if they can, is that agile can provide them those benefits. However, agile is not for everyone. If they decide agile is not for them, we discuss if an iterative approach is best, or an incremental approach is best, or a combination is best. It’s all about what they need for their product development.

If you don’t need a geographically distributed organization, don’t create one. Telecommuting creates one. Instead, make it a policy that everyone come to work. Phase the policy in, as Meyer is. Have a conversation, as Best Buy is.

And, if you got sucked into those crazy workplace architectures, make enough offices/cubicles of large enough size, so that people have a place to put their stuff and work. Oh, and make the cube walls shorter, so people can see me coming, so I don’t have to wear a bike flag. That’s just craziness, too.

Talk With Your People

This is not about anti-parents. This is about bringing working people together for innovation and creativity. How do you solve the problem of long commutes, a reasonable workspace, and core hours?

The best thing you can do is talk about this issue with the people in your company. If you are a manager, don’t think you have all the answers. You might not even understand all the problems.

You don’t have to agree with me. I’m sure I will set off the mommy-wars and the daddy-wars, and the manager-wars, and the employee-wars. Well, I have on my flame-retardant suit. Go ahead. I’m ready! If you have the discussion in your organization about what is best for you, I have done a good job.
 

Reference: Telecommuting, Hoteling, and Managing Product Development from our JCG partner Johanna Rothman at the Managing Product Development blog.


Source : feedproxy[dot]google[dot]com

Monday, April 1, 2013

FitNesse your ScalaTest with custom Scala DSL

This article won’t be about FitNesse. As matter of fact I don’t like this tool very much and it seems to be loosing momentum, judging by the traffic on an official mailing list. Instead we will implement trivial internal DSL on top of Scala to simplify testing code, inspired by DoFixture. DoFixture in FitNesse allows one to write very readable acceptance tests almost in plain English using Wiki pages:
 
 
 
 
 
 

!|CarRegistrationFixtureTest| !1 Registering car!2 Registering brand new car for the first time | register | brand new car | by | any owner | in | any country |

What might not be obvious is that the last line is actually executable and calls good old Java (or Scala for that matter) method:

class CarRegistrationFixtureTest extends DoFixture {     val carService = new CarService     def registerByIn(car: Car, owner: Owner, where: Country) = {        //...    } }

Notice how oddly named registerByIn method maps to “ register brand new car by any owner in any country” wiki syntax. What we will learn today is writing very simple, custom Scala DSL that is even more readable and does not require new tool and testing framework.

The same test written in ScalaTest would look something like this:

class CarRegistrationSpec extends FeatureSpec with GivenWhenThen {     val carService = new CarService()     feature("Registering car") {         scenario("Registering brand new car for the first time") {            Given("Owner and brand new car")            //...             When("Car registered")            carService.registerCar(brandNewCar, anyOwner, anyCountry)             //...        }    }}

Nothing fancy, ordinary registerCar() method call. The rest of the test (as well as the declaration of brandNewCar, anyOwner and anyCountry) is not relevant to our discussion. We can make it a little bit more readable by explicitly naming parameters:

carService.registerCar(car = brandNewCar, owner = anyOwner, where = anyCountry)

However it’s not clear whether this is actually more readable for e.g. non-programmers. But since we already use descriptive FeatureSpec, can we make Scala code a little bit more human eye-friendly? Of course! Our biggest friends are infix notation and fluent API pattern:

def register(car: Car) = new {    def by(owner: Owner) = new {        def in(country: Country) =            carService.registerCar(car, owner, country)    }}

Looks weird, but put this code in your test and enjoy much more fluent call:

register(brandNewCar).by(anyOwner).in(anyCountry)

This is as far as Java can go, but Scala has infix method call syntax, which is equivalent and looks beautiful:

register(brandNewCar) by anyOwner in anyCountry

Why couldn’t we skip first parentheses? It is a limitation on where infix notation can be used (only one-argument method calls on an object). Fortunately we can easily refactor our internal testing DSL by pushing noun (owner) onto first place and using implicit conversion:

implicit def fluentCarRegister(owner: Owner) = new {    def registers(car: Car) = new {        def in(country: Country) =            carService.registerCar(car, owner, country)    }}

…which can be used as follows:

anyOwner registers brandNewCar in anyCountry

If you got lost, the line of code above is still Scala and is still executable. If you don’t quite get what’s happening, here is a desugared syntax:

fluentCarRegister(anyOwner).registers(brandNewCar).in(anyCountry)

Tests are all about readability and maintainability. Many people are scared of DSLs because often they are hard to implement and debug. As I showed in this short article, writing really simple yet impressive test DSL in Scala is both simple and rewarding. Moreover there is no reflection or magic meta-programming.
 

Reference: FitNesse your ScalaTest with custom Scala DSL from our JCG partner Tomasz Nurkiewicz at the NoBlogDefFound blog.


Source : feedproxy[dot]google[dot]com

Function interface – A functional interface in the java.util.function package in Java 8

I had previously written about functional interfaces and their usage. If you are exploring the APIs to be part of Java 8 and especially those APIs which support lambda expressions you will find few interfaces like- Function, Supplier, Consumer, Predicate and others which are all part of the java.util.function package, being used extensively. These interfaces have one abstract method, which is overridden by the lambda expression defined. In this post I will pick Function interface to explain about it in brief and it is one of the interfaces present in java.util.function package.

Function interface has two methods:
 
 

In this post I would like to write about the apply method, creating APIs which accept these interfaces and parameters and then invoke their corresponding methods. We will also look at how the caller of the API can pass in a lambda expression in place of an implementation of the interface. Apart from passing a lambda expression, the users of the API can also pass method references, about which I havent blogged yet.

Function interface is uses in cases where you want to encapsulate some code into a method which accepts some value as an input parameter and then returns another value after performing required operations on the input. The input parameter type and the return type of the method can either be same or different.

Lets look at an API which accepts an implementation of Function interface:

public class FunctionDemo {   //API which accepts an implementation of    //Function interface  static void modifyTheValue(int valueToBeOperated,           Function<Integer, Integer> function){    int newValue = function.apply(valueToBeOperated);    /*     * Do some operations using the new value.     */    System.out.println(newValue);  } }

Now lets look at the code which invokes this API:

public static void main(String[] args) {  int incr = 20;  int myNumber = 10;  modifyTheValue(myNumber, val-> val + incr);  myNumber = 15;  modifyTheValue(myNumber, val-> val * 10);  modifyTheValue(myNumber, val-> val - 100);  modifyTheValue(myNumber, val-> 'somestring'.length() + val - 100);}

You can see that the lambda expressions being created accept one parameter and return some value.

I will update soon about the various APIs which use this Function interface as a parameter. Meanwhile the complete code is:

public class FunctionDemo {  public static void main(String[] args) {    int incr = 20;    int myNumber = 10;    modifyTheValue(myNumber, val-> val + incr);    myNumber = 15;    modifyTheValue(myNumber, val-> val * 10);    modifyTheValue(myNumber, val-> val - 100);    modifyTheValue(myNumber, val-> 'somestring'.length() + val - 100);  }  //API which accepts an implementation of   //Function interface  static void modifyTheValue(int valueToBeOperated,           Function<Integer, Integer> function){    int newValue = function.apply(valueToBeOperated);    /*     * Do some operations using the new value.     */    System.out.println(newValue);  }}

and the output is:

30150-85-75

Note: The above code was compiled using the JDK downloaded from here and Netbeans 8 nightly builds.
 

Reference: Function interface – A functional interface in the java.util.function package in Java 8 from our JCG partner Mohamed Sanaulla at the Experiences Unlimited blog.


Source : feedproxy[dot]google[dot]com

Hope vs. Motivation: Why Big Data needs empathy and emotion

Because, – says Om Malik, one of the most extraordinary thinkers on Silicon Valley and the  founder of GIGAOM -

The problem with data is that the way it is used today, it lacks empathy and emotion. Data is used like a blunt instrument, a scythe trying to cut and tailor a cashmere sweater…

He concludes

The idea of combining data, emotion and empathy as part of a narrative is something every company — old, new, young and mature — has to internalize. If they don’t, they will find themselves on the wrong side of history.

The first reaction most people trained to follow procedures, is disappointment. Derrick Harris writes;

“Some people say big data is wallowing in the trough of disillusionment, but that’s a limited worldview

(but) there are small pockets of technologists who are letting their imaginations lead the way. In a suddenly cliché way of saying it, they’re aiming for 10x improvement rather than 10 percent improvement. They can do that because they now have a base set of analytic technologies and techniques”

Usually the big complains in social enterprise are for loss of privacy. But this is the surface not the reason. It is the unintelligent way of using data, with no empathy and no deep insights. Absolutely no one will get any business from me by filling my  mailing box (the snail mail box)  with junk offers. And like me, there are many people sick of telemarketers phone calls every evening at 8:00 p.m.. Or broadcast prerecorded message reminders from schools and doctors. There is no difference in scientific data. The amount of data collected at the ATLAS detector from the  Large Hadron Collider (LHC) in CERN, Geneva  is described like this:

If all the data from ATLAS would be recorded, this would fill 100,000 CDs per second. This would create a stack of CDs 450 feet high every second, which would reach to the moon and back twice each year. The data rate is also equivalent to 50 billion telephone calls at the same time. ATLAS actually only records a fraction of the data (those that may show signs of new physics) and that rate is equivalent to 27 CDs per minute.

Sure, this is a technological advance to find the Higgs particle inside this massive data. Somebody must have a lot a Hope and Motivation

Figure 2: The shape of the curve Hope versus Motivation can predicts the success


 

Higgs particle discovery needs to correlate to the humans feelings behind. the endeavor. I call them Hope and Motivation. Compare Higgs curve to medieval failed philosopher’s stone. Paraphrasing  Malik Om insight. “The idea of combining data, emotion and empathy as part of a narrative is something every science research team has to internalize.”
 

Reference: Hope vs. Motivation: Why Big Data needs empathy and emotion from our JCG partner Miha Ahronovitz at the The memories of a Product Manager blog.


Source : feedproxy[dot]google[dot]com

Life Beyond Rete – R.I.P Rete 2013 :)

I’m just putting the final touches onto my new algorithm. It merges concepts from Leaps, Collection Oriented Match and Left/Right unlinking, as well as a few ideas of my own. The code is committed, but I’m just getting accumulate to work and writting some more tests. I’ll do a full blog in a week or so, writting about it in more detail, hopefully accompanied with an alpha for people to play with. The algorithm addresses the greedy and wasteful nature of Rete. This will make it suitable for more constrained environments, such as mobile devices, or browsers if we do a JS port with GWT. Further it’s been designed with multi-core utilisation in mind – although I haven’t implemented that yet. For those with an understanding of the terminologies, here is a bullet point list of what I’ve done so far.
 

Rule unlinking

  • With segments to preserve sharing. Bit masks used for right input and segments, for efficient checking.
  • A Segment has it’s bit set, when all right inputs have their bit set.
  • A rule is linked in, when each segment has it’s bit set.
  • No beta evaluation happens until a rule is both fully linked in an popped of the agenda (see lazy rule evaluation)
  • A linked rule can be unlinked, when any of right inputs has no data
    • All full and partial join data is preserved.
      • avoids re-calculation when rule is re-linked
      • Stops further wasted join attempts until the rule is likely to fire
    • GC algorithm is needed, so joins can be removed from memory if not used for some time.
  • I suspect we could use arc consistency to further delay when a bit is set, rather than simple the existing of a right input

Lazy rule evaluation

  • Rule’s beta network is not evaluated when linked. Instead it’s added to the priority queue, only when it pops do we evaluate it’s beta network

Set Oriented propagations

  • All insert, update and deletes are staged for the right inputs, until rule is evaluated.
  • Beta network evaluation starts at the root
    • All inset/update/delete’s are processed together resulting in a set of tuples to be propagated to the next node
    • The set of tuples has separate lists for inserted, updated, deleted tuples.
  • Ensures course grained node evaluation, ideal for multi-core scheduling.
  • Single pass propagation, instead of typical Rete which depth search thrashes the network.
  • Note we do not yet do collection oriented match, which collapses the match space in a node.
    • While we borrowed the collection propagation concept, the defragmentation process of collection oriented match needs a lot more thought, as it has downsides.
    • While not done yet, we will now be able to support set oriented executions, as well as propagations. Ideas for this are outlined here, https://community.jboss.org/wiki/RuleExecutionSemantics, inspired by DADO.

Modify in place/Differential Update

  • Modifies are real, instead of a retract + assert
  • Allows for compensation ‘undo’ actions, as we know what really was deleted and what was updated.
  • Preserves objects, to avoid GC hit.

Property Reactive

  • Patterns can listen and react to specific property changes
    • Think of it as a property change listener, rather than the current class change listener
    • Defaults to listen to constrained fields, users may override what they do or don’t listen to.
    • Uses bit masks to keep it efficient

Tree based graphs

  • Retracts simply need to iterate the graph
  • Allows for efficient ‘modify in place’

Subnetwork support

  • not, exists, accumulates can supported nested groups and patterns
  • Is supported as part of the single pass network evaluation
    • Our tuple set reaches the left input, and then recursively evaluates the subetnworks(s). This then eventually results in a single set of tuples again, which is applied to our current node, resulting in a single set to propagate to the child.

While not complete, here are some TODO items I can think of, to give an idea of near and longer term ideas:

More efficient sub-networking

  • The new design allows for more efficient execution within subnetworks, but we have yet to take advantage of this.

GC Joins

  • Allow joins to be GC’d after a period of time, if they are not used, but also must support recreation while not invalidating the execution sequence of rules (i.e. a rule must not fire again, if it’s already fired)

Different network topologies

  • Rete network’s always join from left to right, this is not always efficient. Treat and Gator networks look at how different topologies can reduce the number of join attempts, it can also improve sharing with our new segmentation based network.

Multi-core work

  • The design now is already queued based, and supports coarse grained units of work. We now need to start creating the thread model and better isolating and separating the alpha network propagation process. This involves refactoring our existing locking model.
  • Efficient testing of overlapping rules is needed – i.e does one rule share segment with another rule. This will allow us to evaluate rules, without sync points.

Intelligent Linking

  • At the moment linking is done by setting a bit, when a right input receives a single fact. Arc consistency can be used to further delay this linking process, only linking in a rule segment and also a rule, when arc consistency is achieved.

MVCC and Transactions

  • The propagation model should support Multi-Version Concurrent Control. This will be necessary to get better multi-core support, and it will enable transactions support.
R.I.P. 
RETE 2013 :)

Reference: Life Beyond Rete – R.I.P Rete 2013 :) from our JCG partner Geoffrey De-Smet at the Drools & jBPM blog.


Source : feedproxy[dot]google[dot]com

Java 8 Lambdas – The missing link to moving away from Java

I learnt functional programming, but then I decided I liked imperative programming better so I switched back.

— Nobody, ever

Moving from imperative programming to functional programming is a very common thing to do today. Blog posts on the internet abound with testimonies about it. Everything I’ve read and every person I’ve talked to, including myself, has the same story. Once they started functional programming, there was no looking back. They loved it, and in the early days, even the small amount they learnt gave them a thirst to
 
learn more.

To me it seems clear, going from imperative programming to functional programming is a one way street under heavy traffic. It’s a diode with a million volts sitting across it. It’s a check valve on a mains water pipe. Not only can you not go back, but it comes with an irresistible desire to explore and learn more that pushes you further into functional programming.

Java 8 Lambdas

With Java 8 lambdas on the way, this poses an interesting turning point for one of the largest groups of developers on the planet. Lambdas in themselves don’t necessarily equate to functional programming. But they do enable it. And as a developer here starts dabbling in functional programming, a library maintainer there, we’ll start to see some new things in Java source code. Methods that previously might have returned null will start returning Optional. Libraries that do IO, for example HTTP client libraries, will start returning CompletableFuture. More and more functional concepts will start creeping into Java interfaces, there will be methods called fold, map, reduce, collect. And so will start the one way street of the Java masses moving from imperative programming to functional programming.

But will Java satisfy their thirst? Looking at the Lambda spec, I suspect not. I see an essence of genius in the Lambda spec, it makes many, many existing libraries instantly usable, with no changes, with Lambdas. The reason for this is that a Lambda is just syntactic sugar for implementing a single-abstract-method (SAM) interface. In Java you’ll find SAM’s everywhere, from Runnable and Callable in the concurrency package, to ActionListener in Swing, to Function and Supplier in Guava, and the list goes on. All of these libraries are Lambda ready today.

However, this also presents a problem. Functional programming gets interesting when you start composing things. The ability to pass functions around and compose them together gives a lot of power – but the Java 8 Lambdas are not composable. Java 8 does provide a Future SAM, but so does Guava, and many other libraries. To compose these together, you’d need all permutations of composition methods. Two SAM’s of the same type aren’t even very simple to compose, at least, not in a traditional Java way, since you can’t add any methods to the SAM, such as a map or transform method, to do the composing.

So, without the ability to do one of the most basic functional concepts, composing functions, can Java ever become a functional language? Maybe there are some creative ways to solve this that I haven’t thought of. And maybe it doesn’t need to, I don’t think the designers of Java 8 Lambdas had any intention of making Java a functional language, so you can’t call this a fault of the Lambda spec. But the problem is the developers, having got a taste for functional programming, as I pointed out earlier, are going to want more, and going to want more fast. Even if Java could become a functional language, I don’t think it will keep up with the movement of Java developers to functional programming.

So I’m going to make a prediction. Java 8 Lambdas will be eagerly adopted. So eagerly that Java itself will be left behind, and the majority of Java developers will move on to a language that meets their needs as eager budding new functional programmers.

Which language?

Before I speculate on which language Java developers will move to, let me first just qualify that I am both biased and ignorant. I work for Typesafe, and so am obviously biased towards Scala. And apart from playing with Haskell and ML at university, I have never used any other functional language in anger. So take my words with a grain of salt, and if you disagree, write your own blog post about it.

Scala as a transitionary language

So firstly, I think Scala makes a great transitionary language for imperative programmers to switch to functional programming. Having got a taste for functional programming with Java 8 Lambdas, a Java developer will find themselves very comfortable in Scala. They can still do everything in the same way they used to, they have vars and mutable collections, they have all the standard Java libraries at their finger tips. And of course, they can start deepening their knowledge in functional programming. So Scala provides a smooth transition from imperative programming to functional programming, you can adopt functional programming as quickly or as slowly as you like.

Scala as the destination language

Having transitioned to functional programming, will developers stay at Scala, or will they move on, like they moved on from Java, in search of a more pure language? My opinion here is no. Broadly speaking, I see two camps in the functional programming community. The first camp sees functional programming as a set of laws that must be followed. For this camp, Scala has a lot of things that are not necessary and/or dangerous, and they would probably not see Scala as the end destination.

The second camp sees functional programming as a powerful tool that should be widely exploited, but not a set of laws that must be followed. This is where I stand, and Scala fills the needs of this camp very well. Functional programming has first class support in Scala, but you can always fall back to imperative when it makes sense. I suspect that the majority of the Java community would be inclined to join this camp, otherwise, they would already be shunning Java and writing Haskell. So I think Java 8 Lambdas are going to be very good for Scala, in that they give Java developers a taste for what Scala will do for them, and thus funnel the masses into Scala development.
 

Reference: Java 8 Lambdas – The missing link to moving away from Java from our JCG partner James Roper at the James and Beth Roper’s blogs blog.


Source : feedproxy[dot]google[dot]com