I have this code below:
DStream.map {
_.message()
}.foreachRDD { rdd =>
rdd.foreachPartition{iter =>
val conf = HBaseUtils.configureHBase("iemployee")
val connection = ConnectionFactory.createConnection(conf)
val table = connection.getTable(TableName.valueOf("""iemployee"""))
iter.foreach{elem =>
/* loop through the records in the partition and push them out to the DB */
}
}
Can someone please tell me if the connection object created val connection = ConnectionFactory.createConnection(conf) here is the same connection object used in each partition (since I never close it) or will a new connection object be created for every partition?
New connection instance for each partition..
Please see the below code & documentation of Connection Factory. it was also mentioned that its callers responsibility to close the connection.
/**
* Create a new Connection instance using the passed <code>conf</code> instance. Connection
* encapsulates all housekeeping for a connection to the cluster. All tables and interfaces
* created from returned connection share zookeeper connection, meta cache, and connections
* to region servers and masters.
* <br>
* The caller is responsible for calling {#link Connection#close()} on the returned
* connection instance.
*
* Typical usage:
* <pre>
* Connection connection = ConnectionFactory.createConnection(conf);
* Table table = connection.getTable(TableName.valueOf("table1"));
* try {
* table.get(...);
* ...
* } finally {
* table.close();
* connection.close();
* }
* </pre>
*
* #param conf configuration
* #param user the user the connection is for
* #param pool the thread pool to use for batch operations
* #return Connection object for <code>conf</code>
*/
public static Connection createConnection(Configuration conf, ExecutorService pool, User user)
throws IOException {
if (user == null) {
UserProvider provider = UserProvider.instantiate(conf);
user = provider.getCurrent();
}
String className = conf.get(ClusterConnection.HBASE_CLIENT_CONNECTION_IMPL,
ConnectionImplementation.class.getName());
Class<?> clazz;
try {
clazz = Class.forName(className);
} catch (ClassNotFoundException e) {
throw new IOException(e);
}
try {
// Default HCM#HCI is not accessible; make it so before invoking.
Constructor<?> constructor =
clazz.getDeclaredConstructor(Configuration.class,
ExecutorService.class, User.class);
constructor.setAccessible(true);
return (Connection) constructor.newInstance(conf, pool, user);
} catch (Exception e) {
throw new IOException(e);
}
}
}
Hope this helps!!
Related
We have several spring boot Rest APIs with hundreds of endpoints.
Are there any tools or libraries that we can use to monitor specific endpoints, logging the request, response, and timings to a custom database?
Any in particular that can be attached to running services already?
I've heard of Actuator, AOP, AspectJ, but I'm not sure it's what we want?
Thanks
You can create an aspect that logs enter/exit logs and time execution for each method of given packages.
To calculate time execution, you can use spring Stopwatch. However, you have to be careful to the performance impacts. (This class isn’t recommended for production environment)
import org.springframework.util.StopWatch;
#Aspect
#Component
public class LoggingAspect {
private final Logger log = LoggerFactory.getLogger(this.getClass());
/**
* Pointcut that matches all services and Web REST endpoints.
*/
#Pointcut("within(#org.springframework.stereotype.Service *)" +
" || within(#org.springframework.web.bind.annotation.RestController *)")
public void springBeanPointcut() {
// Method is empty as this is just a Pointcut, the implementations are in the advices.
}
/**
* Pointcut that matches all Spring beans in the application's endpoint packages.
*/
#Pointcut("within(your.pack.num1..*)" +
" || within(your.pack.num2..*)" +
" || within(your.pack.num3..*)")
public void applicationPackagePointcut() {
// Method is empty as this is just a Pointcut, the implementations are in the advices.
}
/**
* Advice that logs methods throwing exceptions.
*
* #param joinPoint join point for advice
* #param e exception
*/
#AfterThrowing(pointcut = "applicationPackagePointcut() && springBeanPointcut()", throwing = "e")
public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
log.error("Exception in {}.{}() with cause = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), e.getCause() != null ? e.getCause() : "NULL");
}
/**
* Advice that logs when a method is entered and exited.
*
* #param joinPoint join point for advice
* #return result
* #throws Throwable throws IllegalArgumentException
*/
#Around("applicationPackagePointcut() && springBeanPointcut()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
StopWatch stopWatch;
if (log.isDebugEnabled()) {
stopWatch= new StopWatch();
stopWatch.start();
log.debug("Enter: {}.{}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
}
try {
try{
Object result = joinPoint.proceed();
}finally{
stopWatch.stop();
}
if (log.isDebugEnabled()) {
log.debug("Exit: {}.{}() with result = {} and execution time {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), result,stopWatch.getTotalTimeMillis());
}
return result;
} catch (IllegalArgumentException e) {
log.error("Illegal argument: {} in {}.{}()", Arrays.toString(joinPoint.getArgs()),
joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
throw e;
}
}
}
Problem:There is a JMS topic and I've following connection details :
URL:xyz
Connection Factory: jms.xyz
Topic Name: jms.xyz
username:
password:
Is there a working code which creates a subscriber in Spark Scala which consumes the JMS messages from the topic?
I have tried using socketTextStream function of spark streaming, but it has only URL parameter.
I'm looking for a spark streaming function which can have all my 5 parameters :
1) URL
2) Connection Factory
3) Topic Name
4) Username
5) Password
I've tried running in Spark-Shell
I'm looking for a spark streaming function which can have all my 5 parameters and a working spark-scala code which can consume JMS messages from the topic:
1) URL
2) Connection Factory
3) Topic Name
4) Username
5) Password
I am looking for Spark-Shell base commands which I can execute line by line
Q: Can we consume JMS messages from a Topic through Spark Streaming?
Yes. AFAIK there is no silver bullet solution for this.
Based on Messaging provider implementation may vary.
you may need to write a custom receiver from spark docs for that..
See Example 2 which uses jms topic integration with spark-streaming
Example 1 (source):
import org.apache.log4j.Logger;
import org.apache.spark.storage.StorageLevel;
import org.apache.spark.streaming.receiver.Receiver;
import javax.jms.*;
import javax.naming.Context;
import java.util.Hashtable;
public class JMSReceiver extends Receiver<JMSEvent> implements MessageListener
{
private static final Logger log = Logger.getLogger(JMSReceiver.class);
private static final String JNDI_INITIAL_CONTEXT_FACTORY = "org.apache.qpid.jms.jndi.JmsInitialContextFactory";
private static final String JNDI_CONNECTION_FACTORY_NAME = "JMSReceiverConnectionFactory";
private static final String JNDI_QUEUE_NAME = "JMSReceiverQueue";
private static final String JNDI_CONNECTION_FACTORY_KEY_PREFIX = "connectionfactory.";
private static final String JNDI_QUEUE_KEY_PREFIX = "queue.";
private StorageLevel _storageLevel;
private String _brokerURL;
private String _username;
private String _password;
private String _queueName;
private String _selector;
private Connection _connection;
public JMSReceiver(String brokerURL, String username, String password, String queueName, String selector, StorageLevel storageLevel)
{
super(storageLevel);
_storageLevel = storageLevel;
_brokerURL = brokerURL;
_username = username;
_password = password;
_queueName = queueName;
_selector = selector;
log.info("Constructed" + this);
}
#Override
public void onMessage(Message message)
{
try
{
log.info("Received: " + message);
JMSEvent jmsEvent = new JMSEvent(message);
store(jmsEvent);
} catch (Exception exp)
{
log.error("Caught exception converting JMS message to JMSEvent", exp);
}
}
#Override
public StorageLevel storageLevel()
{
return _storageLevel;
}
public void onStart()
{
log.info("Starting up...");
try
{
Hashtable<Object, Object> env = new Hashtable<Object, Object>();
env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_INITIAL_CONTEXT_FACTORY);
env.put(JNDI_CONNECTION_FACTORY_KEY_PREFIX + JNDI_CONNECTION_FACTORY_NAME, _brokerURL);
env.put(JNDI_QUEUE_KEY_PREFIX + JNDI_QUEUE_NAME, _queueName);
javax.naming.Context context = new javax.naming.InitialContext(env);
ConnectionFactory factory = (ConnectionFactory) context.lookup(JNDI_CONNECTION_FACTORY_NAME);
Destination queue = (Destination) context.lookup(JNDI_QUEUE_NAME);
if ((_username == null) || (_password == null))
{
_connection = factory.createConnection();
} else
{
_connection = factory.createConnection(_username, _password);
}
_connection.setExceptionListener(new JMSReceiverExceptionListener());
Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer messageConsumer;
if (_selector != null)
{
messageConsumer = session.createConsumer(queue, _selector);
} else
{
messageConsumer = session.createConsumer(queue);
}
messageConsumer.setMessageListener(this);
_connection.start();
log.info("Completed startup.");
} catch (Exception exp)
{
// Caught exception, try a restart
log.error("Caught exception in startup", exp);
restart("Caught exception, restarting.", exp);
}
}
public void onStop()
{
// Cleanup stuff (stop threads, close sockets, etc.) to stop receiving data
log.info("Stopping...");
try
{
_connection.close();
} catch (JMSException exp)
{
log.error("Caught exception stopping", exp);
}
log.info("Stopped.");
}
private class JMSReceiverExceptionListener implements ExceptionListener
{
#Override
public void onException(JMSException exp)
{
log.error("Connection ExceptionListener fired, attempting restart.", exp);
restart("Connection ExceptionListener fired, attempting restart.");
}
}
#Override
public String toString()
{
return "JMSReceiver{" +
"brokerURL='" + _brokerURL + '\'' +
", username='" + _username + '\'' +
", password='" + _password + '\'' +
", queueName='" + _queueName + '\'' +
", selector='" + _selector + '\'' +
'}';
}
}
your JMSInputDstream will look like
import org.apache.spark.storage.StorageLevel
import org.apache.spark.streaming._
import org.apache.spark.streaming.dstream._
import org.apache.spark.streaming.receiver.Receiver
private[streaming]
class JMSInputDStream(
#transient ssc_ : StreamingContext,
brokerURL: String,
username: String,
password: String,
queuename: String,
selector: String,
storageLevel: StorageLevel
) extends ReceiverInputDStream[JMSEvent](ssc_) {
override def getReceiver(): Receiver[JMSEvent] = {
new JMSReceiver(brokerURL, username, password, queuename, selector, storageLevel)
}
}
Example 2 using activemq and JmsTopicReceiver.scala :
import org.apache.spark.Logging
import org.apache.spark.storage.StorageLevel
import javax.{jms => jms}
/** Simple class of a receiver that can be run on worker nodes to receive the data from JMS Topic.
*
* In JMS a Topic implements publish and subscribe semantics.
* When you publish a message it goes to all the subscribers who are interested - so zero to many subscribers will receive a copy of the message.
* Only subscribers who had an active subscription at the time the broker receives the message will get a copy of the message.
*
* {{{
* val sc: SparkContext = SparkContext.getOrCreate(conf)
* val ssc: StreamingContext = new StreamingContext(sc, Seconds(...))
*
* val stream: InputDStream[String] = ssc.receiverStream(new JmsTopicReceiver(
* topicName = "testTopic",
* transformer = { msg => msg.asInstanceOf[javax.jms.TextMessage].getText() },
* connectionProvider = { () => {
* val cf = new org.apache.activemq.ActiveMQConnectionFactory("tcp://localhost:61616")
* cf.setOptimizeAcknowledge(true)
* cf.createConnection("username", "password")
* }}
* ))
*
* ...
*
* ssc.start()
* ssc.awaitTermination()
* }}}
*
* #param connectionProvider provides <CODE>javax.jms.Connection</CODE> for the receiver.
* #param transformer (pre)transforms <CODE>javax.jms.Message</CODE> to appropriate class (it's required to do this before populate the result).
* #param topicName the name of required <CODE>javax.jms.Topic</CODE>.
* #param messageSelector only messages with properties matching the message selector expression are delivered.
* #param storageLevel flags for controlling the storage of an RDD.
* #tparam T RDD element type.
*/
class JmsTopicReceiver[T] (
connectionProvider: (() => jms.Connection),
transformer: (jms.Message => T),
topicName: String,
messageSelector: Option[String] = None,
storageLevel: StorageLevel = StorageLevel.MEMORY_AND_DISK_SER_2
) extends AbstractJmsReceiver[T](
messageSelector = messageSelector,
storageLevel = storageLevel
) with Logging {
override protected def buildConnection(): jms.Connection = connectionProvider()
override protected def transform(message: jms.Message): T = transformer(message)
override protected def buildDestination(session: jms.Session): jms.Destination = session.createTopic(topicName)
}
Example 3 : Solace used custom receiver of spark : This way I worked long back when spark 1.3 was there,
Solace-JMS-Integration-Spark-Streaming.pdf
Further reading : Processing Data from MQ with Spark Streaming: Part 1 - Introduction to Messaging, JMS & MQ
I have a problem with eclipse,it says failed to instantiate the type xmppconnection,please tell me what's wrong with my code
here is my code
}
public boolean login(String a,String p){
ConnectionConfiguration config = new ConnectionConfiguration("gcm.googleapis.com", PORT);
/** */
config.setSASLAuthenticationEnabled(false);
/** */
config.setDebuggerEnabled(true);
/** connection */
XMPPConnection connection = new XMPPConnection(config);
try {
/** */
connection.connect();
/** */
connection.login(a, p);
/** ?*/
//ClientSendThread cst=new ClientSendThread(connection);
//cst.start();
//ManageClientThread.addClientSendThread(a, cst);
return true;
} catch (XMPPException e) {
e.printStackTrace();
}
return false;
}
}
Try this:
new smack version using `XMPPTCPConnection connection = new XMPPTCPConnection(config)`
instead of `XMPPConnection connection = new XMPPConnection(config);`
I'm using BoneCP for connection pooling jdbc connections to my mysql database. I'm using the bonecp example in my REST application.
If every REST request is opening and closing the connection pool, doesn't this defeat the point of connection pooling in the first place?
Here is the code:
public class ExampleJDBC {
/** Start test
* #param args none expected.
*/
public static void main(String[] args) {
BoneCP connectionPool = null;
Connection connection = null;
try {
// load the database driver (make sure this is in your classpath!)
Class.forName("org.hsqldb.jdbcDriver");
} catch (Exception e) {
e.printStackTrace();
return;
}
try {
// setup the connection pool
BoneCPConfig config = new BoneCPConfig();
config.setJdbcUrl("jdbc:hsqldb:mem:test"); // jdbc url specific to your database, eg jdbc:mysql://127.0.0.1/yourdb
config.setUsername("sa");
config.setPassword("");
config.setMinConnectionsPerPartition(5);
config.setMaxConnectionsPerPartition(10);
config.setPartitionCount(1);
connectionPool = new BoneCP(config); // setup the connection pool
connection = connectionPool.getConnection(); // fetch a connection
if (connection != null){
System.out.println("Connection successful!");
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS"); // do something with the connection.
while(rs.next()){
System.out.println(rs.getString(1)); // should print out "1"'
}
}
connectionPool.shutdown(); // shutdown connection pool.
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
Yes, it would defeat the purpose to open or close the connection pool more than once in the (typical) lifecycle of your application. You should fetch a connection from the pre-established pool each time instead.
I have a problem with datasource binding in ListGrid with smartGWT. I have GWT-RPC-DataSource and i have set it as my datasource
grid.setDataSource(ds);
On one button click I have some changes in my datasource and I am generating new datasource and rebinding with smartgwt's grid. but it fails. I have tried grid.redraw() function to redraw the grid.
Below is my class for GWTRPCDATASOURCE
public abstract class GwtRpcDataSource extends DataSource {
/**
* Creates new data source which communicates with server by GWT RPC. It is
* normal server side SmartClient data source with data protocol set to
* <code>DSProtocol.CLIENTCUSTOM</code> ("clientCustom" - natively supported
* by SmartClient but should be added to smartGWT) and with data format
* <code>DSDataFormat.CUSTOM</code>.
*/
public GwtRpcDataSource() {
setDataProtocol(DSProtocol.CLIENTCUSTOM);
setDataFormat(DSDataFormat.CUSTOM);
setClientOnly(false);
}
/**
* Executes request to server.
*
* #param request
* <code>DSRequest</code> being processed.
* #return <code>Object</code> data from original request.
*/
#Override
protected Object transformRequest(DSRequest request) {
String requestId = request.getRequestId();
DSResponse response = new DSResponse();
response.setAttribute("clientContext",
request.getAttributeAsObject("clientContext"));
// Asume success
response.setStatus(0);
switch (request.getOperationType()) {
case FETCH:
executeFetch(requestId, request, response);
break;
case ADD:
executeAdd(requestId, request, response);
break;
case UPDATE:
executeUpdate(requestId, request, response);
break;
case REMOVE:
executeRemove(requestId, request, response);
break;
default:
// Operation not implemented.
break;
}
return request.getData();
}
/**
* Executed on <code>FETCH</code> operation.
* <code>processResponse (requestId, response)</code> should be called when
* operation completes (either successful or failure).
*
* #param requestId
* <code>String</code> extracted from
* <code>DSRequest.getRequestId ()</code>.
* #param request
* <code>DSRequest</code> being processed.
* #param response
* <code>DSResponse</code>. <code>setData (list)</code> should be
* called on successful execution of this method.
* <code>setStatus (<0)</code> should be called on failure.
*/
protected abstract void executeFetch(String requestId, DSRequest request,
DSResponse response);
/**
* Executed on <code>ADD</code> operation.
* <code>processResponse (requestId, response)</code> should be called when
* operation completes (either successful or failure).
*
* #param requestId
* <code>String</code> extracted from
* <code>DSRequest.getRequestId ()</code>.
* #param request
* <code>DSRequest</code> being processed.
* <code>request.getData ()</code> contains record should be
* added.
* #param response
* <code>DSResponse</code>. <code>setData (list)</code> should be
* called on successful execution of this method. Array should
* contain single element representing added row.
* <code>setStatus (<0)</code> should be called on failure.
*/
protected abstract void executeAdd(String requestId, DSRequest request,
DSResponse response);
/**
* Executed on <code>UPDATE</code> operation.
* <code>processResponse (requestId, response)</code> should be called when
* operation completes (either successful or failure).
*
* #param requestId
* <code>String</code> extracted from
* <code>DSRequest.getRequestId ()</code>.
* #param request
* <code>DSRequest</code> being processed.
* <code>request.getData ()</code> contains record should be
* updated.
* #param response
* <code>DSResponse</code>. <code>setData (list)</code> should be
* called on successful execution of this method. Array should
* contain single element representing updated row.
* <code>setStatus (<0)</code> should be called on failure.
*/
protected abstract void executeUpdate(String requestId, DSRequest request,
DSResponse response);
/**
* Executed on <code>REMOVE</code> operation.
* <code>processResponse (requestId, response)</code> should be called when
* operation completes (either successful or failure).
*
* #param requestId
* <code>String</code> extracted from
* <code>DSRequest.getRequestId ()</code>.
* #param request
* <code>DSRequest</code> being processed.
* <code>request.getData ()</code> contains record should be
* removed.
* #param response
* <code>DSResponse</code>. <code>setData (list)</code> should be
* called on successful execution of this method. Array should
* contain single element representing removed row.
* <code>setStatus (<0)</code> should be called on failure.
*/
protected abstract void executeRemove(String requestId, DSRequest request,
DSResponse response);
private ListGridRecord getEditedRecord(DSRequest request) {
// Retrieving values before edit
JavaScriptObject oldValues = request
.getAttributeAsJavaScriptObject("oldValues");
// Creating new record for combining old values with changes
ListGridRecord newRecord = new ListGridRecord();
// Copying properties from old record
JSOHelper.apply(oldValues, newRecord.getJsObj());
// Retrieving changed values
JavaScriptObject data = request.getData();
// Apply changes
JSOHelper.apply(data, newRecord.getJsObj());
return newRecord;
}
}
I have implemented this abstract class to my own datasource class named NTDatasource.
public class NTDataSource extends GwtRpcDataSource {
public static int total = 991;
Record[] records;
public NTDataSource() {
}
public void setData(List<NTListGridField> lstFields, Record[] records) {
// setTestData(records);
for (NTListGridField lstField : lstFields) {
if (lstField.getType() == ListGridFieldType.DATE) {
DataSourceDateField dateField = new DataSourceDateField(
lstField.getName());
dateField.setHidden(lstField.getAttributeAsBoolean("visible"));
if (lstField.getName().equals("id")) {
dateField.setHidden(true);
}
addField(dateField);
} else {
DataSourceTextField textField = new DataSourceTextField(
lstField.getName());
textField.setHidden(lstField.getAttributeAsBoolean("visible"));
if (lstField.getName().equals("id")) {
textField.setHidden(true);
textField.setPrimaryKey(true);
}
addField(textField);
}
}
total = records.length;
this.records = records;
}
#Override
protected void executeFetch(String requestId, DSRequest request,
DSResponse response) {
// assume we have 1000 items.
response.setTotalRows(total);
int end = request.getEndRow();
if (end > total) {
end = total;
}
Record returnRecords[] = new Record[end
- request.getStartRow()];
for (int i = request.getStartRow(); i < end; i++) {
ListGridRecord r = new ListGridRecord();
r = (ListGridRecord) records[i];
returnRecords[i - request.getStartRow()] = r;
}
GWT.log(" called from " + request.getStartRow() + " to "
+ request.getEndRow() + " result " + returnRecords.length, null);
response.setData(returnRecords);
processResponse(requestId, response);
}
#Override
protected void executeAdd(String requestId, DSRequest request,
DSResponse response) {
// TODO Auto-generated method stub
}
#Override
protected void executeUpdate(String requestId, DSRequest request,
DSResponse response) {
// TODO Auto-generated method stub
}
#Override
protected void executeRemove(String requestId, DSRequest request,
DSResponse response) {
// TODO Auto-generated method stub
}
}
I have solve this question myself.
the answer is i need to use grid.fetchData() method and bind datasource one more time to use it.... !! I hope it might help someone else.
Try grid.invalidateCache() .This call will clear the current data in the grid and executes the NTDataSource.executeFetch method.