I am implementing push notifications, but I receive TIMEOUT exception when calling getToken.
This issue only happen on some devices as SC-03D (4.0).
Here's my IntentService which I use to register token:
public class RegistrationIntentService extends IntentService {
private static final String TAG = "GCM";
public static final String TOKEN_ID = "registration_id";
/**
* Constructor
*/
public RegistrationIntentService() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
try {
// In the (unlikely) event that multiple refresh operations occur simultaneously, ensure that they are processed sequentially.
synchronized (TAG) {
// Initially this call goes out to the network to retrieve the token, subsequent calls are local.
InstanceID instanceID = InstanceID.getInstance(this);
String gcm_sender_id = getString(R.string.gcm_sender_id);
String token = instanceID.getToken(gcm_sender_id, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
String storageToken = PrefsHelper.getTokenId(this);
Log.d(TAG, "GCM Registration Token: " + token);
}
} catch (Exception e) {
Log.d(TAG, "Failed to complete token refresh", e);
}
}
You need to try registering the token Using Exponential Back-Off
Following code might help you
public class RegistrationIntentService extends IntentService {
private static final String TAG = "GCM";
public static final String TOKEN_ID = "registration_id";
private final static int MAX_ATTEMPTS = 5;
private final static int BACKOFF_MILLI_SECONDS = 2000;
/**
* Constructor
*/
public RegistrationIntentService() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
// In the (unlikely) event that multiple refresh operations occur simultaneously, ensure that they are processed sequentially.
synchronized (TAG) {
Random random = new Random();
String token = null;
InstanceID instanceID = InstanceID.getInstance(this);
long backoff = BACKOFF_MILLI_SECONDS + random.nextInt(1000);
for (int i = 1; i <= MAX_ATTEMPTS; i++) {
try {
token = instanceID.getToken(getString(R.string.gcm_sender_id);, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
if(null != token && !token.isEmpty()) {
break;
}
} catch (IOException e) {
//Log exception
}
if (i == MAX_ATTEMPTS) {
break;
}
try {
Thread.sleep(backoff);
} catch (InterruptedException e1) {
break;
}
// increase backoff exponentially
backoff *= 2;
}
// further processing for token goes here
}
}
For more information see this
The previous solution is almost correct; the missing part is actually breaking the retry if you indeed got the token:
for (int i = 1; i <= MAX_ATTEMPTS; i++) {
try{
_token = instanceID.getToken(getString(R.string.gcm_defaultSenderId), GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
if (!(_token == null || _token.isEmpty())) {
break;
}
}
catch (IOException e){
Log.d(TAG, "Couldn't get token; waiting "+String.valueOf(backoff) + "ms");
if (i == MAX_ATTEMPTS) {
break;
}
try {
Thread.sleep(backoff);
}
catch (InterruptedException e1) {
break;
}
}
backoff *= 2;
}
if(_token == null){
//Couldn't get the token!!!
}
Related
I'm taking my first steps with Java Sockets and Threads.
I want to try make synchonized connection with serwer where multiple threades adds their request to the queue and signle thread send all this request. In the meantime other threads wait for there resoults.
How it's work:
Client ask servert to log in by caling method
User user = logIn("sdasd");
public User logIn(String name){
System.out.println("!Log in");
//Function create request
RequestHandler<User> request = new RequestHandler<>("logIn", name, out, results);
//Request is added to queue
requestQueue.addLast(request);
RequestStatus status;
//Thread who call this function wait for request to be handle (changed status)
while (true){
status = request.getStatus();
System.out.println(status);
if (status == RequestStatus.SUCCESSFUL) {
System.out.println("Try to get result: ");
User user = request.result();
System.out.println(user.getName());
return request.result();
}
if(status == RequestStatus.FAILED) {
return null;
}
}
}
In the meantime other thread send request to server:
new Thread(new Runnable() {
#Override
public void run() {
while(isConnected()){
//is request to be handle?
if(requestQueue.size() != 0){
//remove request form queue
RequestHandler request = (RequestHandler) requestQueue.removeFirst();
//change request status
request.setStatus(RequestStatus.IN_PROGRESS);
System.out.println("!Request: ");
System.out.println(request.getStatus());
//process request
request.request();
//change request status to finished
request.setStatus(RequestStatus.SUCCESSFUL);
System.out.print("!Request end: ");
System.out.println(request.getStatus());
}
}
Iterator<Request> iterator = requestQueue.iterator();
for (Iterator<Request> it = iterator; it.hasNext(); ) {
Request request = it.next();
request.setStatus(RequestStatus.FAILED);
}
}
}).start();
Inside class RequestHandler is process this code:
#Override
public void request() {
try {
//send commend
out.writeObject(requestCommend);
//wait for result (other thread handle this functionality)
while(!results.containsKey(commend)){}
//attach result
result = (T) results.remove(commend);
} catch (IOException e) {
e.printStackTrace();
}
}
When the request is send to the server other thread wait for response for the server and add result to the HashMap:
new Thread(new Runnable() {
#Override
public void run() {
while(isConnected()) {
try {
String commend = (String) in.readObject();
if(commend.charAt(0) == '#') { // # mean its result of request
Object object = in.readObject();
//This is debug case to see everything work properly
if(object == null){
System.out.println("!I am null");
}else{
System.out.println("I am user: " +((User) object).getName());
}
System.out.println(commend);
results.put(commend, object);
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}).start();
This is it. Required code for this question:
public class ServerConnection extends Socket{
public static final int PORT = 8888;
private ObjectInputStream in;
private ObjectOutputStream out;
private LinkedList<Request> requestQueue;
private ConcurrentHashMap<String, Object> results;
public ServerConnection() throws IOException{
super("localhost", PORT);
System.out.println("Connected to the server.");
in = new ObjectInputStream(getInputStream());
out = new ObjectOutputStream(getOutputStream());
requestQueue = new LinkedList<>();
results = new ConcurrentHashMap<>();
new Thread(new Runnable() {
#Override
public void run() {
while(isConnected()){
if(requestQueue.size() != 0){
RequestHandler request = (RequestHandler) requestQueue.removeFirst();
request.setStatus(RequestStatus.IN_PROGRESS);
System.out.println("!Request: ");
System.out.println(request.getStatus());
request.request();
request.setStatus(RequestStatus.SUCCESSFUL);
System.out.print("!Request end: ");
System.out.println(request.getStatus());
}
}
Iterator<Request> iterator = requestQueue.iterator();
for (Iterator<Request> it = iterator; it.hasNext(); ) {
Request request = it.next();
request.setStatus(RequestStatus.FAILED);
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
while(isConnected()) {
try {
String commend = (String) in.readObject();
if(commend.charAt(0) == '#') { // # mean its result of request
Object object = in.readObject();
//This is debug case
if(object == null){
System.out.println("!I am null");
}else{
System.out.println("I am user: " +((User) object).getName());
}
System.out.println(commend);
results.put(commend, object);
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}).start();
}
public User logIn(String name){
System.out.println("!Log in");
RequestHandler<User> request = new RequestHandler<>("logIn", name, out, results);
requestQueue.addLast(request);
RequestStatus status;
while (true){
status = request.getStatus();
System.out.println(status);
if (status == RequestStatus.SUCCESSFUL) {
System.out.println("Try to get result: ");
User user = request.result();
System.out.println(user.getName());
return request.result();
}
if(status == RequestStatus.FAILED) {
return null;
}
}
}
public ArrayList<Room> getListOfRooms(){
Request<ArrayList<Room>> request = new RequestHandler<>("listOfRooms", out, results);
requestQueue.addLast(request);
while (true){
RequestStatus status = request.getStatus();
if (status == RequestStatus.SUCCESSFUL)
return request.result();
if(status == RequestStatus.FAILED) {
return null;
}
}
}
}
RequestHandler looks like this:
public class RequestHandler<T> implements Request<T>{
private T result;
private RequestStatus status = RequestStatus.NEW;
private ObjectOutputStream out;
private String commend;
private String requestCommend;
private ConcurrentHashMap<String, Object> results;
public RequestHandler(String commend, String parameters, ObjectOutputStream out, ConcurrentHashMap<String, Object> results) {
this.commend = "#" + commend;
this.requestCommend = "?" + commend + ":" + parameters;
this.out = out;
this.results = results;
}
public RequestHandler(String commend, ObjectOutputStream out, ConcurrentHashMap<String, Object> results) {
this.commend = "#" + commend;
this.requestCommend = "?" + commend;
this.out = out;
this.results = results;
}
#Override
public void request() {
try {
out.writeObject(requestCommend);
while(!results.containsKey(commend)){}
result = (T) results.remove(commend);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public T result() {
return result;
}
#Override
public RequestStatus getStatus() {
return status;
}
#Override
public void setStatus(RequestStatus status) {
this.status = status;
}
}
The output looks like this WHEN ITS WORK:
Connected to the server.
!Log in
NEW
IN_PROGRESS
...
IN_PROGRESS
!Request: IN_PROGRESS
IN_PROGRESS
...
IN_PROGRESS
I am user: sdsad
#logIn
IN_PROGRESS
IN_PROGRESS
SUCCESSFUL
!Request end: SUCCESSFUL
Try to get result:
sdsad
But when I COMMENT one debug msg I got this:
Connected to the server.
!Log in
!Request: IN_PROGRESS
I am user: dfdsfsdf4324
#logIn
!Request end: SUCCESSFUL
And the loop while(true) never end becouse I got always status IN_PROGRESS.
That's why I want to ask you why it's happen? Is Java have some weird way to optimalize output of functions to make is faster and is it thinking if it was reapet milion times so it has to be this state always?
I have implemented a thread in an Android app that is invoked every minute, the invocation of the process occur through an Alarm Manager.
#Override
public void onReceive(Context context, Intent intent) {
try {
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock;
if (powerManager != null) {
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Send-data");
wakeLock.acquire(10 * 60 * 1000L);
new Thread(new SendPolicyData(context)).start();
wakeLock.release();
}
} catch (Exception e) {
wil.WriteFile("1)AlarmSendData - Exception: " + e.toString());
}
}
The code contained in the thread extract a set of data from a database that must be sent through posts to a server, the access to resources is controlled via a semaphore.
#SuppressWarnings("ResultOfMethodCallIgnored")
public class SendPolicyData implements Runnable {
private static final WriteInLogFile wil = new WriteInLogFile();
private final Context ctx;
public SendPolicyData(Context ctx) {
this.ctx = ctx;
}
public void run() {
try {
SemaphoreDTS.getInstance().goIn();
Authentication singleCall = new Authentication();
Utilities utilities = new Utilities(ctx);
DbGest dbGest = DbGest.getInstance(ctx);
if (utilities.checkConnection()) {
int lastProcessedID = -1;
int attempts = 0;
Cursor cursor = dbGest.freeQuery("SELECT id, label, value, priority FROM " + TABLE_DATATOSEND + " ORDER BY priority,dateIns");
if (cursor != null) {
cursor.moveToFirst();
if (cursor.getCount() > 0) {
do {
int toProcessID = cursor.getInt(cursor.getColumnIndex("id"));
String value = cursor.getString(cursor.getColumnIndex("value"));
String labelString = cursor.getString(cursor.getColumnIndex("label"));
if (lastProcessedID == toProcessID) {
if (attempts <= 5) {
attempts++;
Thread.sleep(3000);
} else {
attempts = 0;
dbGest.changeDTSRecordPriority(toProcessID);
}
}
switch (labelString) {
case "photo":
//DO STUFF
break;
lastProcessedID = toProcessID;
} while (cursor.moveToNext());
}
cursor.close();
}
}
} catch (Exception e) {
SemaphoreDTS.getInstance().goOut();
wil.WriteFile("7)SendPolicyData - Exception: " + e.toString());
} finally {
SemaphoreDTS.getInstance().goOut();
}
SemaphoreDTS.getInstance().goOut();
}
}
This is the source code of the semaphore that I use to manage the access to the resources.
public class SemaphoreDTS {
private static SemaphoreDTS instance;
private final Semaphore semaphore;
private final WriteInLogFile wil = new WriteInLogFile();
private SemaphoreDTS() {
this.semaphore = new Semaphore(1, true);
}
public static SemaphoreDTS getInstance() {
if (instance == null) {
instance = new SemaphoreDTS();
}
return instance;
}
public synchronized void goIn() {
try {
semaphore.acquire();
} catch (Exception e) {
wil.WriteFile("1)SemaphoreDTS - Exception: " + e.toString());
}
}
public synchronized void goOut() {
try {
semaphore.release();
} catch (Exception e) {
wil.WriteFile("2)SemaphoreDTS - Exception: " + e.toString());
}
}
}
During the tests that I did, it often happens that the semaphore remains blocked, for some reason the necessary release is not invoked in order to be able to perform new acquire.
I think I have written the code correctly and I don't understand where I am wrong.
In this code's block:
catch (Exception e) {
SemaphoreDTS.getInstance().goOut();
wil.WriteFile("7)SendPolicyData - Exception: " + e.toString());
} finally {
SemaphoreDTS.getInstance().goOut();
}
SemaphoreDTS.getInstance().goOut();
You always have two calls .goOut(), because finally block always will invoke.
When you call .release() (in your method .goOut()) semaphore gets availible permit, i.e instead 1 permit your semaphore gets 2 permits. I think problem starts here. Try to delete calls `.goOut() method everywhere but not in finally()
I am trying to give a pop up alert message when my ThreadpoolExecutor is finished executing. It is searching email addresses from websites, once it is done I want a alert message as "Completed". Here is my Thread :-
public class Constant
{
public static final int NUM_OF_THREAD = 60;
public static final int TIME_OUT = 10000;
}
ThreadPoolExecutor poolMainExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool
(Constant.NUM_OF_THREAD);
Here is my Searching Operation class :-
class SearchingOperation implements Runnable {
URL urldata;
int i;
Set<String> emailAddresses;
int level;
SearchingOperation(URL urldata, int i, Set<String> emailAddresses, int level) {
this.urldata = urldata;
this.i = i;
this.emailAddresses = emailAddresses;
this.level = level;
if (level != 1)
model.setValueAt(urldata.getProtocol() + "://" + urldata.getHost() + "/contacts", i, 3);
}
public void run() {
BufferedReader bufferreader1 = null;
InputStreamReader emailReader = null;
System.out.println(this.i + ":" + poolMainExecutor.getActiveCount() + ":" + level + ";" + urldata.toString());
try {
if (level < 1) {
String httpPatternString = "https?:\\/\\/(www\\.)?[-a-zA-Z0-9#:%._\\+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9#:%_\\+.~#?&//=]*)";
String httpString = "";
BufferedReader bufferreaderHTTP = null;
InputStreamReader httpReader = null;
try {
httpReader = new InputStreamReader(urldata.openStream());
bufferreaderHTTP = new BufferedReader(httpReader
);
StringBuilder rawhttp = new StringBuilder();
while ((httpString = bufferreaderHTTP.readLine()) != null) {
rawhttp.append(httpString);
}
if (rawhttp.toString().isEmpty()) {
return;
}
List<String> urls = getURL(rawhttp.toString());
for (String url : urls) {
String fullUrl = getMatchRegex(url, httpPatternString);
if (fullUrl.isEmpty()) {
if (!url.startsWith("/")) {
url = "/" + url;
}
String address = urldata.getProtocol() + "://" + urldata.getHost() + url;
fullUrl = getMatchRegex(address, httpPatternString);
}
if (!addressWorked.contains(fullUrl) && fullUrl.contains(urldata.getHost())) {
addressWorked.add(fullUrl);
sendToSearch(fullUrl);
}
}
} catch (Exception e) {
//System.out.println("652" + e.getMessage());
//e.printStackTrace();
return;
} finally {
try {
if (httpReader != null)
bufferreaderHTTP.close();
} catch (Exception e) {
// e.printStackTrace();
}
try {
if (httpReader != null)
httpReader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
String someString = "";
emailReader = new InputStreamReader(urldata.openStream());
bufferreader1 = new BufferedReader(
emailReader);
StringBuilder emailRaw = new StringBuilder();
while ((someString = bufferreader1.readLine()) != null) {
if (someString.contains("#")) {
emailRaw.append(someString).append(";");
}
}
//Set<String> emailAddresses = new HashSet<String>();
String emailAddress;
//Pattern pattern = Pattern
//.compile("\\b[a-zA-Z0-9.-]+#[a-zA-Z0-9.-]+\\.[a-zA-Z0-9.-]+\\b");
Pattern
pattern = Pattern
.compile("\\b[a-zA-Z0-9.-]+#[a-zA-Z0-9.-]+\\.[a-zA-Z0-9.-]+\\b");
Matcher matchs = pattern.matcher(emailRaw);
while (matchs.find()) {
emailAddress = (emailRaw.substring(matchs.start(),
matchs.end()));
// //System.out.println(emailAddress);
if (!emailAddresses.contains(emailAddress)) {
emailAddresses.add(emailAddress);
// //System.out.println(emailAddress);
if (!foundItem.get(i)) {
table.setValueAt("Found", i, 4);
foundItem.set(i, true);
}
String emails = !emailAddresses.isEmpty() ? emailAddresses.toString() : "";
model.setValueAt(emails, i, 2);
model.setValueAt("", i, 3);
}
}
} catch (Exception e) {
//System.out.println("687" + e.getMessage());
} finally {
try {
if (bufferreader1 != null)
bufferreader1.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
if (emailReader != null)
emailReader.close();
} catch (Exception e) {
e.printStackTrace();
}
Thread.currentThread().interrupt();
return;
}
}
After this the final snippet :-
private void sendToSearch(String address) throws Throwable {
SearchingOperation operation = new SearchingOperation(new URL(address), i,
emailAddresses, level + 1);
//operation.run();
try {
final Future handler = poolMainExecutor.submit(operation);
try {
handler.get(Constant.TIME_OUT, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
e.printStackTrace();
handler.cancel(false);
}
} catch (Exception e) {
//System.out.println("Time out for:" + address);
} catch (Error error) {
//System.out.println("Time out for:" + address);
} finally {
}
}
Implement Callable<Void> instead of Runnable and wait for all the task to terminate by calling Future<Void>.get():
class SearchingOperation implements Callable<Void>
{
public Void call() throws Exception
{
//same code as in run()
}
}
//submit and wait until the task complete
Future<Void> future = poolMainExecutor.submit(new SearchingOperation()).get();
Use ThreadPoolExecutor.awaitTermination():
Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
As in your code, you create your ThreadPoolExecutor first
ThreadPoolExecutor poolMainExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(Constant.NUM_OF_THREAD);
Then, you need to add Tasks to it:
poolMainExecutor.execute(myTask);
poolMainExecutor.submit(myTask);
execute will return nothing, while submit will return a Future object. Tasks must implement Runnable or Callable. An object of SearchingOperation is a task for example. The thread pool will execute the tasks in parallel, but each task will be executed by one thread. That means to effectively use NUM_OF_THREAD Threads you need to add at least NUM_OF_THREAD Tasks.
(Optional) Once you got all jobs to work, shutdown your pool. This will prevent new tasks from being submitted. It won't affect running tasks.
poolMainExecutor.shutdown();
At the end, you need to wait for all Tasks to complete. The easiest way is by calling
poolMainExecutor.awaitTermination(Integer.MAX_VALUE, TimeUnit.DAYS);
You should adjust the amount of time you want to wait for the tasks to finish before throwing an exception.
Now that the work is done, notify the user. A simple way is to call one of the Dialog presets from JOptionPane, like:
JOptionPane.showMessageDialog(null, "message", "title", JOptionPane.INFORMATION_MESSAGE);
It will popup a little window with title "title", the message "message", an "information" icon and a button to close it.
This code can be used., it will check whether the execution is completed in every 2.5 seconds.
do {
System.out.println("In Progress");
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (poolMainExecutor.getActiveCount() != 0);
System.out.println("Completed");
I have developed a client/server chat application using Java and I wish to know how can I remove a user from an array. When a specific client log-in the username is saved in username array and client ID in client array. To allow the server to accept multiple clients, I am using threads. Now can anyone guide me on how to remove a user from the array and also close the connection for that user.
Adding a new client and saving the ID in client array
public class AddClient implements Runnable {
Thread t;
AddClient(String tot) {
t = new Thread(this, tot);
t.start();
}
public void run() {
while (true) {
try {
try {
waitClient();
} catch (Exception ex) {
ex.printStackTrace();
}
for (int i = 0; i < client.length; i++) {
if (client[i] == 0) {
client[i] = i + 1;
id = i;
break;
}
}
//set stream to send and receive data
out[client[id]] = new ObjectOutputStream(connect.getOutputStream());
out[client[id]].flush();
in[client[id]] = new ObjectInputStream(connect.getInputStream());
The username is saved in the username array
username[client[id]] = cm.sender; //Add user in username[] array
Removing user
public synchronized void removeUser(int number) {
int position = number;
System.out.println("Server removing user " + username[number] + "which is client " + number);
for (int i = 0; i <= client.length; i++) {
if (position == client[i]) {
System.out.println("User to be remove found");
try {
client[i + 1] = client[i];
in[position].close();
out[position].close();
username[position] = null;
position = position - 1;
} catch (Exception e) {
e.printStackTrace();
}
}
}
I am trying to use HashTable to add and remove the client
public class ChatServerProtocol {
private String nick;
private AddClient a;
private Hashtable<String, AddClient> nicks = new Hashtable<String, AddClient>();
private boolean add_nick(String nick, AddClient a) {
if (nicks.containsKey(nick)) {
return false;
} else {
nicks.put(nick, a);
return true;
}
}
private boolean remove_nick(String nick, AddClient a) {
if (!(nicks.containsKey(nick))) {
return false;
} else {
nicks.remove(nick);
return true;
}
}
public ChatServerProtocol(AddClient a) throws IOException {
nick = null;
a = a;
}
But now how do I call the method add_nick. Whenever a client log-in the username is sent to the server and the server reads it as cm.sender. I also need to include the thread variable. So how to add the username so that later i can remove it.
ChatServerProtocol.add_nick(cm.sender);
No, saving in database won't be a good idea.. Remember you are saving details only for the length of the session and basic concept of database is to use it after the session. What happens if your session gets interruped because of network issues etc?
Just use Map instead of plain arrays, using key as client ID and value as username.. removing username will be a plain call such as map.remove(clientID);
EDIT AS YOU ASKED: Note that this code is not complete and only as much as you gave..
public class AddClient implements Runnable {
Thread t;
private Map<int, String> users = new HashMap <int, String>();
AddClient(String tot) {
t = new Thread(this, tot);
t.start();
}
public void run() {
while (true) {
try {
try {
waitClient();
} catch (Exception ex) {
ex.printStackTrace();
}
int clientId = users.size() + 1;
users.put(clientId, cm.sender);
//set stream to send and receive data
out[clientId] = new ObjectOutputStream(connect.getOutputStream());
out[clientId].flush();
in[clientId] = new ObjectInputStream(connect.getInputStream());
REMOVE USER METHOD
public synchronized void removeUser(int number) {
if(users.containsKey(number)) {
System.out.println("Server removing user " + users.get(number) + "which is client " + number);
users.remove(number);
} else {
System.out.println("User not in session");
}
}
I would like to know how to access the Service and Domains properly in this sample class placed in src/java folder
public class NewsIngestion implements Runnable {
private String str;
private int num;
private Logger log = Logger.getLogger("grails.app");
private static boolean isRunning;
private Thread t;
private WorkerJobService jobService;
private NewsService newsService;
public NewsIngestion(String s, int n)
{
jobService = new WorkerJobService();
newsService = new NewsService();
str = s;
num = n;
isRunning = false;
t = new Thread (this, "NewsIngestion");
}
public void run ()
{
while(isRunning){
try{
if(jobService.isJobEnabled("ConsumeFeedsJob") && jobService.lockJob("ConsumeFeedsJob")){
log.info("${this.class.name}: ConsumeFeedsJob started");
try{
// get all sources
List sources = (List) InvokerHelper.invokeMethod(RSSFeed.class, "list", null);
for(int i = 0; i < sources.size(); i++) {
RSSFeed s = (RSSFeed) sources.get(i);
// check if it's time to read the source
int diff = DateTimeUtil.getSecondsDateDiff(s.getLastChecked(), new Date());
if(s.getLastChecked() == null || diff >= s.getCheckInterval()){
List keyword_list = (List) InvokerHelper.invokeMethod(Keyword.class, "list", null);
for(int j = 0; j < keyword_list.size(); j++) {
String keyword = (String) keyword_list.get(j);
try{
newsService.ingestNewsFromSources(keyword, s);
}catch(Exception e){
log.error("${this.class.name}: ${e}");
}
log.debug("Completed reading feeds for ${keyword}.");
log.info("${this.class.name}: Reading feeds for '${keyword}' (${s.feedName}) took ${Float.toString(st2.getDuration())} second(s).");
}
s.setLastChecked(new Date());
InvokerHelper.invokeMethod(RSSFeed.class, "save", null);
}
log.info("${this.class.name}: Reading feeds for '${s.feedName}' for all keywords took ${Float.toString(st.getDuration())} second(s).");
}
}catch(Exception e){
log.error("${this.class.name}: Exception: ${e}");
}
log.info("${this.class.name}: ConsumeFeedsJob ended.");
// unlock job
jobService.unlockJob("ConsumeFeedsJob");
}
log.info("alfred: success");
}
catch (Exception e){
log.info("alfred exception: " + e.getMessage());
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
log.info(e.getMessage());
}
}
}
public void start() {
if(t == null){
t = new Thread (this, "NewsIngestion");
}
if(!isRunning){
isRunning = true;
t.start();
}
}
public void stop() {
isRunning = false;
}
public boolean isRunning() {
return isRunning;
}
}
I'm encountering this error message:
No Hibernate Session bound to thread,
and configuration does not allow
creation of non-transactional one here
Thanks.
You shouldn't instantiate the service class by yourself, but instead take the class instance from the main context
import org.codehaus.groovy.grails.commons.ApplicationHolder
def ctx = ApplicationHolder.application.mainContext
def newsService = ctx.newsService
If you're using Java
import org.codehaus.groovy.grails.commons.ApplicationHolder
public class SomeClass {
SomeService someService;
public SomeClass() {
someService = (SomeService) ApplicationHolder.getApplication().getMainContext().getBean("someService");
}
}
Consider using Spring and #Transactional annotation or AOP.