Exception when I try create JNDI Subcontext from JUnit - java

My purpose - create test for DAO layer. My Hibernate config has datasourse specified throught JNDI. Also I use Jboss 5.1 so transaction lookup is necessary.
<property name="hibernate.connection.datasource">java:jdbc/MysqlDS</property>
<property name="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
<property name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</property>
To make test I need bind these things. Todo this I create class util to bind. Full code below
public class RegisteringJNDIWithDataSource {
public static final String JNDI_MY_DS = "java:jdbc/MysqlDS";
private static final String MYSQL_USER = "user";
private static final String MYSQL_PASS = "pass";
private static final String MYSQL_HOST = "localhost";
public static String CTX_INITIAL_CONTEXT_FACTORY = "org.jnp.interfaces.NamingContextFactory";
public static String CTX_URL_PKG_RPEFIXES = "org.jboss.naming";
private void startRegistry() throws NamingException, RemoteException {
System.out.println(LocateRegistry.getRegistry());
Registry reg = LocateRegistry.createRegistry(1099);
NamingServer server = new NamingServer();
NamingContext.setLocal(server);
System.out.println("RMI registry Stared.");
}
public InitialContext createInitialContextContext() throws NamingException {
System.setProperty(Context.URL_PKG_PREFIXES, CTX_URL_PKG_RPEFIXES);
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, CTX_INITIAL_CONTEXT_FACTORY);
InitialContext initialContextcontext = new InitialContext();
return initialContextcontext;
}
/**
* Registry the following JNDIs
*
* #throws RemoteException
* #throws NamingException
*/
public void registrate() throws RemoteException, NamingException {
startRegistry();
InitialContext ic;
ic = createInitialContextContext();
String[] cxts = JNDI_MY_DS.split("/");
String inCxt = cxts[0];
createSubcontext(ic, inCxt);
for (int i = 1; i < cxts.length - 1; i++) {
// if the data source name is like java:/comp/mysqldatasource
// this takes care of creating subcontexts in jndi
inCxt = inCxt + "/" + cxts[i];
createSubcontext(ic, inCxt);
}
ic.rebind(JNDI_MY_DS, createMysqlDataSource("db_name"));
// the following requires JBoss dependent class. May be sth can be done to generalize this
TransactionManager tm = new CustomTXNManager();
ic.bind("java:/TransactionManager", tm);
UserTransaction ut = new CustomUserTransaction();
ic.bind("UserTransaction", ut);
}
private static Context createSubcontext(Context ctx, String cxtName) throws NamingException {
System.out.println(" creating subcontext " + cxtName);
Context subctx = ctx;
Name name = ctx.getNameParser("").parse(cxtName);
for (int pos = 0; pos < name.size(); pos++) {
String ctxName = name.get(pos);
try {
subctx = (Context) ctx.lookup(ctxName);
} catch (NameNotFoundException e) {
subctx = ctx.createSubcontext(ctxName);
}
// The current subctx will be the ctx for the next name component
ctx = subctx;
}
return subctx;
}
public void unregistrate() throws NamingException {
InitialContext context;
context = createInitialContextContext();
context.unbind(JNDI_MY_DS);
}
private MysqlConnectionPoolDataSource createMysqlDataSource(String database) throws NamingException {
MysqlConnectionPoolDataSource dataSource;
dataSource = new MysqlConnectionPoolDataSource();
dataSource.setUser(MYSQL_USER);
dataSource.setPassword(MYSQL_PASS);
dataSource.setServerName(MYSQL_HOST);
dataSource.setPort(3306);
dataSource.setDatabaseName(database);
return dataSource;
}
public static void main(String args[]) {
RegisteringJNDIWithDataSource dataSource = new RegisteringJNDIWithDataSource();
try {
dataSource.registrate();
} catch (RemoteException ex) {
ex.printStackTrace();
} catch (NamingException ex) {
ex.printStackTrace();
}
}
public static class CustomTXNManager extends TransactionManagerImple implements Serializable {
private static final long serialVersionUID = 1L;
public CustomTXNManager() {
}
}
public static class CustomUserTransaction extends UserTransactionImple implements Serializable {
private static final long serialVersionUID = 1L;
public CustomUserTransaction() {
}
}
}
All works fine if call from console. But when I call this from JUnit I got exception.
#Test
public void test() throws RemoteException, NamingException {
RegisteringJNDIWithDataSource j = new RegisteringJNDIWithDataSource();
j.registrate();
}
javax.naming.OperationNotSupportedException
at com.sun.jndi.rmi.registry.RegistryContext.createSubcontext(RegistryContext.java:230)
at javax.naming.InitialContext.createSubcontext(InitialContext.java:464)

Related

Using jsmpp for sending asynchronous messages to SMSC server

we have a message campaign where we send over 100k messages (SMS) a day. So we are a client of SMSC server. We have no influence on SMSC server code. Before some time, we had around 80-90 message per second, now frequency dropped to 15 messages per second, according to tcpdumps.
I have few information regarding this, so I will try to explain best as I can.
So we are using Spring Boot 2.7 and open source jsmpp (3.0.0) library for sending SMS messages (PDU commands) to SMSC.
While reading about protocol (page 40), I noticed that there is a way to send messages asynchronously by providing a seqence_number. The code example is here. But I am not sure if that is going to help...
The code:
#Component
public class ClientConfig {
#Autowired
private MessageReceiverListener msgListener;
#Autowired
private SessionStateListener sessionListener;
private SMPPSession session;
public String charset = "ISO-10646-UCS-2";
public long idleReceiveTimeout = 65000;
public long checkBindingTimeout = 12000;
public long timeout = 7000;
public int enquireLinkTimeout = 15000;
public String hostIp = "someIpAddress";
public int port = 5000;
public String final systemId = "someSystemId";
public String final password = "password";
public BindType bindType = BindType.BIND_TRX; //transceiver
public String systemType = null;
public String addressRange = null;
public TypeOfNumber addrTon = TypeOfNumber.UNKNOWN;
public NumberingPlanIndicator addrNpi = NumberingPlanIndicator.UNKNOWN;
protected synchronized void tryToConnectToSmsc() throws Exception {
try {
// Connect to host
BindParameter bp = new BindParameter(bindType, systemId, password, systemType, addrTon, addrNpi, addressRange);
session = new SMPPSession();
session.setEnquireLinkTimer(enquireLinkTimer);
session.connectAndBind(host, port, bp, timeout);
session.setMessageReceiverListener(msgListener);
session.addSessionStateListener(sessionListener);
}
// Main connection failed.
catch (Exception e) {
//log and re-attempt connection logic here
}
}
}
The listeners:
#Component
public class MySessionListenerImpl implements SessionStateListener {
#Override
public void onStateChange(SessionState newState, SessionState oldState, Session source) {
//TODO
}
}
#Service
public class SmsListenerImpl implements MessageReceiverListener {
#Override
public void onAcceptDeliverSm(DeliverSm deliverSm) throws ProcessRequestException {
//TODO
}
#Override
public void onAcceptAlertNotification(AlertNotification alertNotification) {}
#Override
public DataSmResult onAcceptDataSm(DataSm dataSm, Session session) throws ProcessRequestException {
return null;
}
}
Message sending service:
#Service
public class MessageSendingServiceImpl extends ClientConfig implements MessageSendingService{
private final ESMClass esmClass = new ESMClass();
private final byte protocolId = (byte) 0;
private final byte priorityFlag = (byte) 1;
private final TimeFormatter formatter = new AbsoluteTimeFormatter();
private final byte defaultMsgId = (byte) 0;
public SmsAdapterServiceImpl() {
super();
}
#PostConstruct
public synchronized void init() throws Exception {
super.tryToConnectToSmsc();
}
#Override
public String send(DomainObject obj){ //DomainObject -> contains fields: id, to, from, text, delivery, validity;
String serviceType = null;
//source
TypeOfNumber sourceTON = TypeOfNumber.NATIONAL; //there is some logic here which determines if it is INTERNATIOANL, ALPHANUMERIC etc...
NumberPlaningIndicator sourceNpi = NumberPlaningIndicator.ISDN; //constant...
String sourcePhone = obj.getFrom();
//destination
TypeOfNumber destinationTON = TypeOfNumber.NATIONAL; //there is some logic here which determines if it is INTERNATIOANL, ALPHANUMERIC etc...
NumberPlaningIndicator destinationNpi = NumberPlaningIndicator.ISDN; //constant...
String destinationPhone = obj.getTo();
String scheduledDeliveryTime = null;
if (obj.getDelivery() != null) scheduledDeliveryTime = formatter.format(obj.getDelivery());
String validityPeriodTime = null;
if (obj.getValidity() != null) validityPeriodTime = formatter.format(obj.getValidity());
Map<Short, OptionalParameter> optionalParameters = new HashMap<>();
String text = obj.getText();
if ( text.length() > 89 ) { //set text as payload instead of message text
OctetString os = new OctetString(OptionalParameter.Tag.MESSAGE_PAYLOAD.code(), text, "ISO-10646-UCS-2"); //"ISO-10646-UCS-2" - encoding
optionalParameters.put(os.tag, os);
text = "";
}
String msgId =
session.submitShortMessage( serviceType ,
sourceTON ,
sourceNpi ,
sourcePhone ,
destinationTON ,
destinationNpi ,
destinationPhone ,
esmClass ,
protocolId ,
priorityFlag ,
scheduledDeliveryTime ,
validityPeriodTime ,
new RegisteredDelivery() ,
ReplaceIfPresentFlag.DEFAULT.value() ,
new GeneralDataCoding(Alphabet.ALPHA_UCS2) ,
defaultMsgId ,
text.getBytes("ISO-10646-UCS-2") ,
optionalParameters.values().toArray(new OptionalParameter[0]));
return msgId;
}
}
Client code which invokes the service (it is actually a scheduler job):
#Autowired private MessageSendingService messageSendingService;
#Scheduled(cron)
public void execute() {
List<DomainObject> messages = repository.findMessages(pageable, config.getBatch()); //up to several thousand
start(messages);
ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(getSchedulerConfiguration().getPoolSize(), new NamedThreadFactory("Factory"));
List<DomainObject> domainObjects = Collections.synchronizedList(messages);
List<List<DomainObject>> domainObjectsPartitioned = partition(domainObjects.size(), config.getPoolSize()); //pool size is 4
for (List<DomainObject> list: domainObjectsPartitioned ) {
executorService.execute(new Runnable() {
#Override
public void run() {
try {
start(list);
} catch (Exception e) {
e.printStackTrace();
}
});
}
executorService.shutdown();
}
}
private void start(List<DomainObject> list){
for (DomainObject> obj : list) {
String mid = messageSendingService.send(obj);
//do smtg with id...
}
}

Dynamically load from a properties file in java

I have a config.properties files with names like this:
names=john,jane
Then I have a class that access that file and loads the names. And I have another class that get a name from somewhere and if that name is in the config.properties prints "SUCCESS". The problem is that if I add names to the config.properties, I have to run again the program, it doesn´t load dynamically. What is the alternative to this?
public class PropertiesFile {
private static final char OPENFILES_CONFIG_DELIMITER = ',';
private static final String OPENFILES_CONFIG = "config.properties";
private static org.apache.commons.configuration2.Configuration config;
static {
try {
Parameters params = new Parameters();
FileBasedConfigurationBuilder<FileBasedConfiguration> builder = new FileBasedConfigurationBuilder<FileBasedConfiguration>(PropertiesConfiguration.class)
.configure(params.properties()
.setFileName(OPENFILES_CONFIG)
.setListDelimiterHandler(new DefaultListDelimiterHandler(OPENFILES_CONFIG_DELIMITER)));
config = builder.getConfiguration(); }
catch (ConfigurationException cE) {
//...
}
}
public static Set<String> load() {
String[] thingsToExecute = config.getStringArray("names");
return new HashSet<String>(Arrays.asList(thingsToExecute));
}
}
public class OpenFiles {
private static Set<String> toExecute;
public static void main(String[] args) {
updateToExecute();
connect();
}
private static void connect() {
//code that obatins JSONObject
if (obj4.has("name")) {
String personName = obj4.get("name").toString();
updateToExecute();
if (toExecute.contains(personName)) {
System.out.println("SUCCESS");
} else {
System.out.println(personName+"is not in the list");
}
}
}
private static void updateToExecute() {
toExecute = PropertiesFile.load();
}
}

Minifying progressbar (data:image/gif;base64)

I am trying to minify all my css files and one line is making problem. It is background url of .ui-progressbar .ui-progressbar-overlay:
background:url("data:image/gif;base64,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");
I am using granule plugin for compressing with this implementation (first layer):
public class AcceleratorCompressTag extends CompressTag{
public static final String COMPREST_TAG_CONTENT = CompressTag.class.getName() + "Content";
public static final String COMPREST_TAG_JS = CompressTag.class.getName() + "js";
public static final String COMPREST_TAG_CSS = CompressTag.class.getName() + "css";
private static final String NOT_PROCESS_PARAMETER = "granule";
private static final String METHOD = null;
private static final String ID = null;
private static final String OPTIONS = null;
private static final String BASEPATH = null;
private String urlpattern = null;
#Override
public int doAfterBody() throws JspTagException {
final HttpServletRequest httpRequest = new RemoveEncodingHttpServletRequestWrapper(
(HttpServletRequest) pageContext.getRequest(), urlpattern);
final BodyContent bodyContent = getBodyContent();
final String oldBody = bodyContent.getString();
bodyContent.clearBody();
if (httpRequest.getParameter(NOT_PROCESS_PARAMETER) != null) {
final boolean process = CompressorSettings.getBoolean(httpRequest.getParameter(NOT_PROCESS_PARAMETER), false);
if (!process) {
httpRequest.getSession().setAttribute(NOT_PROCESS_PARAMETER, Boolean.TRUE);
} else {
httpRequest.getSession().removeAttribute(NOT_PROCESS_PARAMETER);
}
}
if (httpRequest.getSession().getAttribute(NOT_PROCESS_PARAMETER) != null) {
try {
getPreviousOut().print(oldBody);
} catch (final IOException e) {
throw new JspTagException(e);
}
return SKIP_BODY;
}
try {
final CompressTagHandler compressor = new CompressTagHandler(ID, METHOD, OPTIONS, BASEPATH);
final RealRequestProxy runtimeRequest = new RealRequestProxy(httpRequest);
final String newBody = compressor.handleTag(runtimeRequest, runtimeRequest, oldBody);
getPreviousOut().print(newBody);
} catch (final Exception e) {
throw new JspTagException(e);
}
return SKIP_BODY;
}
public String getUrlpattern() {
return urlpattern;
}
public void setUrlpattern(final String urlpattern) {
this.urlpattern = urlpattern;
}
}
My guess is that i need to perform Base64 Encoding in Java or maybe to increase stack size for JVM because i am getting this error:
SEVERE: Servlet.service() for servlet [CompressServlet] in context with path [] threw exception [Servlet execution threw an exception] with root cause
java.lang.StackOverflowError
at java.util.regex.Pattern$GroupHead.match(Unknown Source)
at java.util.regex.Pattern$Loop.match(Unknown Source)
Can anyone help me with this?
Try using CSS Minifier - By chilts - #andychilton.
https://cssminifier.com/

why static block Cannot execute in sequence but jump into the other method in java?

We used a special database,so i want to write a database connection Pool,there is something wrong with the code, when i debug into the static block,at first JVM worked in the Properties properties = new Properties(); but next step is int i = 0; i dont know why it ingored the other code in the static block
public class GoldDataSource {
private static String goldip;
private static int goldport;
private static String username;
private static String password;
private static int maxPollSize;
private static LinkedList<Server> list = new LinkedList<Server>();
private static Logger logger = LoggerFactory.getLogger(GoldDataSource.class);
static {
try {
Properties properties = new Properties();
InputStream is = GoldDataSource.class.getClassLoader().getResourceAsStream("/conf/db/gold.properties");
properties.load(is);
goldip = properties.getProperty("gold.ip");
goldport = Integer.parseInt(properties.getProperty("gold.port"));
username = properties.getProperty("gold.username");
password = properties.getProperty("gold.password");
maxPollSize = Integer.parseInt(properties.getProperty("gold.pool.maxPollSize"));
for (int i = 0; i < maxPollSize; i++) {
Server server = new ServerImpl(goldip, goldport, username, password);
server.connect();
server.login();
list.add(server);
}
} catch (Exception e) {
....
}
}
public synchronized static Server getServer() {
try {
int i = 0;
while (true) {
Server aServer = list.removeFirst();
if (aServer != null) {
return aServer;
} else {
if (i >= 3) {
return aServer;
}
Thread.sleep(500);
i++;
}
}
} catch (Exception e) {
...
return null;
}
}
public static void closeServer(Server aServer) {
list.addLast(aServer);
}}
I used Server server = GoldDataSource.getServer(); to get connection,but when it executed Properties properties = new Properties();then jump into the code int i = 0; which in the getServer() method
I edited the code with singleton pattern,it worked ,but i still do not understand why the old code didn't worked , and i catched "java.lang.reflect.InvocationTargetException" in the first catch block old code.
public class GoldDataSource {
private static String goldip;
private static int goldport;
private static String username;
private static String password;
private static int maxPollSize;
private static LinkedList<Server> list = new LinkedList<Server>();
private static InputStream is;
private static GoldDataSource aDataSource = new GoldDataSource();
private static Logger logger = LoggerFactory.getLogger(GoldDataSource.class);
private goldDataSource() {
try {
Properties properties = new Properties();
is = GoldDataSource.class.getClassLoader().getResourceAsStream("/conf/db/gold.properties");
properties.load(is);
goldip = properties.getProperty("gold.ip");
goldport = Integer.parseInt(properties.getProperty("gold.port"));
username = properties.getProperty("gold.username");
password = properties.getProperty("gold.password");
maxPollSize = Integer.parseInt(properties.getProperty("gold.pool.maxPollSize"));
for (int i = 0; i < maxPollSize; i++) {
Server server = new ServerImpl(goldip, goldport, username, password);
server.connect();
server.login();
list.add(server);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static goldDataSource getDateSource() {
return aDataSource;
}
public synchronized Server getServer() {
try {
int i = 0;
while (true) {
Server aServer = list.removeFirst();
if (aServer != null) {
return aServer;
} else {
if (i >= 3) {
return aServer;
}
Thread.sleep(500);
i++;
}
}
} catch (Exception e) {
logger.error("get connection error:" + e.toString());
return null;
}
}
public void closeServer(Server aServer) {
list.addLast(aServer);
}
}

My Storm Topology neither working(not generating output) nor failing (not generating errors or exceptions)

I have a topology in which I am trying to count word occurrences which are being generated by SimulatorSpout (not real Stream) and after that write to MySQL database table, the table scheme is very simple:
Field | Type | ...
ID | int(11) | Auto_icr
word | varchar(50) |
count | int(11) |
But I am facing weird problem(as I beforementioned)
I successfully submitted The Topology to my Storm Cluster which consists of 4 supervisors, and I can see the flow of the Topology in Storm Web UI
(no exceptions) but when I checked the MySQL table, to my surprise, the table is empty...
ANY COMMENTS, SUGGESTIONS ARE WELCOME...
Here are spouts and bolts:
public class MySQLConnection {
private static Connection conn = null;
private static String dbUrl = "jdbc:mysql://192.168.0.2:3306/test?";
private static String dbClass = "com.mysql.jdbc.Driver";
public static Connection getConnection() throws SQLException, ClassNotFoundException {
Class.forName(dbClass);
conn = DriverManager.getConnection(dbUrl, "root", "qwe123");
return conn;
}
}
============================= SentenceSpout ===============================
public class SentenceSpout extends BaseRichSpout{
private static final long serialVersionUID = 1L;
private boolean _completed = false;
private SpoutOutputCollector _collector;
private String [] sentences = {
"Obama delivered a powerfull speech against USA",
"I like cold beverages",
"RT http://www.turkeyairline.com Turkish Airlines has delayed some flights",
"don't have a cow man...",
"i don't think i like fleas"
};
private int index = 0;
public void open (Map config, TopologyContext context, SpoutOutputCollector collector) {
_collector = collector;
}
public void nextTuple () {
_collector.emit(new Values(sentences[index]));
index++;
if (index >= sentences.length) {
index = 0;
Utils.waitForSeconds(1);
}
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("sentence"));
}
public void ack(Object msgId) {
System.out.println("OK: " + msgId);
}
public void close() {}
public void fail(Object msgId) {
System.out.println("FAIL: " + msgId);
}
}
============================ SplitSentenceBolt ==============================
public class SplitSentenceBolt extends BaseRichBolt {
private static final long serialVersionUID = 1L;
private OutputCollector _collector;
public void prepare (Map config, TopologyContext context, OutputCollector collector) {
_collector = collector;
}
public void execute (Tuple tuple) {
String sentence = tuple.getStringByField("sentence");
String httpRegex = "((https?|ftp|telnet|gopher|file)):((//)|(\\\\))+[\\w\\d:##%/;$()~_?\\+-=\\\\\\.&]*";
sentence = sentence.replaceAll(httpRegex, "").replaceAll("RT", "").replaceAll("[.|,]", "");
String[] words = sentence.split(" ");
for (String word : words) {
if (!word.isEmpty())
_collector.emit(new Values(word.trim()));
}
_collector.ack(tuple);
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("word"));
}
}
=========================== WordCountBolt =================================
public class WordCountBolt extends BaseRichBolt {
private static final long serialVersionUID = 1L;
private HashMap<String , Integer> counts = null;
private OutputCollector _collector;
private ResultSet resSet = null;
private Statement stmt = null;
private Connection _conn = null;
private String path = "/home/hduser/logOfStormTops/logger.txt";
String rLine = null;
public void prepare (Map config, TopologyContext context, OutputCollector collector) {
counts = new HashMap<String, Integer>();
_collector = collector;
}
public void execute (Tuple tuple) {
int insertResult = 0;
int updateResult = 0;
String word = tuple.getStringByField("word");
//----------------------------------------------------
if (!counts.containsKey(word)) {
counts.put(word, 1);
try {
insertResult = wordInsertIfNoExist(word);
if (insertResult == 1) {
_collector.ack(tuple);
} else {
_collector.fail(tuple);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
} else {
//-----------------------------------------------
counts.put(word, counts.get(word) + 1);
try {
// writing to db
updateResult = updateCountOfExistingWord(word);
if (updateResult == 1) {
_collector.ack(tuple);
} else {
_collector.fail(tuple);
}
// Writing to file
BufferedWriter buffer = new BufferedWriter(new FileWriter(path));
buffer.write("[ " + word + " : " + counts.get("word") + " ]");
buffer.newLine();
buffer.flush();
buffer.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("{word-" + word + " : count-" + counts.get(word) + "}");
}
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
}
// *****************************************************
public int wordInsertIfNoExist(String word) throws ClassNotFoundException, SQLException {
String query = "SELECT word FROM wordcount WHERE word=\"" + word + "\"";
String insert = "INSERT INTO wordcount (word, count) VALUES (\"" + word + "\", 1)";
_conn = MySQLConnection.getConnection();
stmt = _conn.createStatement();
resSet = stmt.executeQuery(query);
int res = 0;
if (!resSet.next()) {
res = stmt.executeUpdate(insert);
} else {
System.out.println("Yangi qiymatni kirityotrganda nimadir sodir bo'ldi");
}
resSet.close();
stmt.close();
_conn.close();
return res;
}
public int updateCountOfExistingWord(String word) throws ClassNotFoundException, SQLException {
String update = "UPDATE wordcount SET count=count+1 WHERE word=\"" + word + "\"";
_conn = MySQLConnection.getConnection();
stmt = _conn.createStatement();
int result = stmt.executeUpdate(update);
//System.out.println(word + "'s count has been updated (incremented)");
resSet.close();
stmt.close();
_conn.close();
return result;
}
}
========================= WordCountTopology ==============================
public class WordCountTopology {
private static final String SENTENCE_SPOUT_ID = "sentence-spout";
private static final String SPLIT_BOLT_ID = "split-bolt";
private static final String COUNT_BOLT_ID = "count-bolt";
private static final String TOPOLOGY_NAME = "NewWordCountTopology";
#SuppressWarnings("static-access")
public static void main(String[] args) throws AlreadyAliveException, InvalidTopologyException {
SentenceSpout spout = new SentenceSpout();
SplitSentenceBolt splitBolt = new SplitSentenceBolt();
WordCountBolt countBolt = new WordCountBolt();
TopologyBuilder builder = new TopologyBuilder();
builder.setSpout(SENTENCE_SPOUT_ID, spout, 2);
builder.setBolt(SPLIT_BOLT_ID, splitBolt, 4).shuffleGrouping(SENTENCE_SPOUT_ID);
builder.setBolt(COUNT_BOLT_ID, countBolt, 4).fieldsGrouping(SPLIT_BOLT_ID, new Fields("word"));
Config config = new Config();
config.setMaxSpoutPending(100);
config.setDebug(true);
StormSubmitter submitter = new StormSubmitter();
submitter.submitTopology(TOPOLOGY_NAME, config, builder.createTopology());
}
}
It is because the _collector.ack(tuple) is not being called when there is exception thrown. When there are too many pending tuple, spout will stop sending new tuples. Try throwing out RuntimeException instead of printStackTrace.

Categories