I have a transactional method at Service layer which call a static method where i am starting a thread for some async task(again some database operation). Does calling a static method from transactional scope can make some db connection leakage problem ?
Below is a sample code explaining the use case.
#Override
#Transactional
public void createRecords(Record r1, Record r2, HttpServletRequest request) {
saveSomeData(r1,r2.getScore());
// Call a Static Method that open a seperate thread
AsyncTasker.doSomeThing(r2);
saveNewData(r2);
}
AsyncTasker.java
public class AsyncTasker {
private static final Logger logger = LoggerFactory.getLogger(AsyncTasker.class);
private static ExecutorService executorService = Executors.newFixedThreadPool(10);
public static void doSomeThing(Record r){
try{
ClearTask clearTask = new ClearTask(r);
executorService.submit(clearTask);
}
catch(Exception e){
logger.error("Error in ClearTask task execution " + r +" : Exception "+ e);
}
}
}
class ClearTask implements Runnable{
private Record r;
ClearTask(Record r){
this.r = r;
}
#Override`enter code here`
public void run() {
Token.deleteAllData(r); // Static method making a rest call
}
}
Related
Usecase:
There is a module which Listens for events in synchronous mode. In the same module using the EmitterProccessor, the event is converted to Flux and made as infinite stream of events. Now there is a upstream module which can subscribes for these event streams. The problem here is how can I dynamically merge these streams to one and then subscribe in a single stream. A simple example is, let us say there are N number of sensors, we can dynamically register these sensors and start listening for measurements as stream of data in single stream after merging them into one stream. Here is the code sample written to mock this behavior.
Create callback and start listening for events
public interface CallBack {
void callBack(int name);
void done();
}
#Slf4j
#RequiredArgsConstructor
public class CallBackService {
private CallBack callBack;
private final Function<Integer, Integer> func;
public void register(CallBack intf) {
this.callBack = intf;
}
public void startServer() {
log.info("Callback started..");
IntStream.range(0, 10).forEach(i -> {
callBack.callBack(func.apply(i));
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
log.info("Callback finished..");
callBack.done();
}
}
Convert the events to streams using event proccessor
#Slf4j
public class EmitterService implements CallBack {
private EmitterProcessor<Integer> emitterProcessor;
public EmitterService(){
emitterProcessor = EmitterProcessor.create();
}
public EmitterProcessor<Integer> getEmmitor() {
return emitterProcessor;
}
#Override
public void callBack(int name) {
log.info("callbakc {} invoked", name);
//fluxSink.next(name);
emitterProcessor.onNext(name);
}
public void done() {
//fluxSink.complete();
emitterProcessor.onComplete();
}
}
public class WrapperService {
EmitterService service1;
ExecutorService service2;
public Flux<Integer> startService(Function<Integer, Integer> func) {
CallBackService service = new CallBackService(func);
service1 = new EmitterService();
service.register(service1);
service2 = Executors.newSingleThreadExecutor();
service2.submit(service::startServer);
return service1.getEmmitor();
}
public void shutDown() {
service1.getEmmitor().onComplete();
service2.shutdown();
}
}
Subscribe for the events
#Slf4j
public class MainService {
public static void main(String[] args) throws InterruptedException {
TopicProcessor<Integer> stealer = TopicProcessor.<Integer>builder().share(true).build();
CountDownLatch latch = new CountDownLatch(20);
WrapperService n1 =new WrapperService();
WrapperService n2 =new WrapperService();
// n1.startService(i->i).mergeWith(n2.startService(i->i*2)).subscribe(stealer);
n1.startService(i->i).subscribe(stealer);
n2.startService(i->i*2).subscribe(stealer);
stealer.subscribeOn(Schedulers.boundedElastic())
.subscribe(x->{
log.info("Stole=>{}", x);
latch.countDown();
log.info("Latch count=>{}", latch.getCount());
});
latch.await();
n1.shutDown();
n2.shutDown();
stealer.shutdown();
}
}
Tried to use TopicProccessor with no success. In the above code subscription happens for first source, for second source there is no subscription. however if use n1.startService(i->i).mergeWith(n2.startService(i->i*2)).subscribe(stealer); subscription works, but there is no dynamic behavior in this case. Need to change subscriber every time.
I have a repository.save() method called inside a scheduler. But it is not saving anything to the database.
Following is my scheduler
#Component
#Transactional
#Slf4j
public class WomConditionActionJob {
#Autowired
private Environment env;
#Autowired
private ECCRepository eCCRepository;
#Autowired
private WOCRepository wOCRepository;
#Autowired
private PSRepository pSRepository;
#Scheduled(fixedDelayString = "${wCATrigger.polling.frequency}", initialDelayString = "${wCATrigger.initial.delay}")
public void execute() {
try {
final PauseStatus pause = pSRepository.findByPSName(PSName.PAUSE);
pauseCondition(pause,threshold);
} catch (Exception e) {
log.error("Exception Occured {}", e);
}
}
private void pauseCondition(final PauseStatus pause, final Integer threshold) {
WOTCondition wotCId = workOrderConditionRepository.findById(1).get();
wotCId.setPauseStatus(pause);
wotCId.setIsUserAction(Boolean.FALSE);
workOrderConditionRepository.save(wotConditionbyId);
conditionCount.setErrorCount(0);
errorConditionCountRepository.save(conditionCount);
}
}
I trying using saveAndFlush() but that time I got Following error
[pool-2-thread-1]|ERROR|[o.s.s.s.TaskUtils$LoggingErrorHandler.handleError(96)]|Unexpected error occurred in scheduled task.
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:873)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:710)
Adding this solved my issue
#Transactional(propagation=Propagation.REQUIRES_NEW)
Example
#Scheduled(cron = "0/5 * * * * *")
#Transactional(propagation=Propagation.REQUIRES_NEW)
#Override
public void scheduleJob() {
Message message = new Message();
message.setMessageId(UUID.randomUUID().toString());
message.setAccountId("accountId");
message.setSent(2L);
message.setFailed(2L);
message.setDelivered(2L);
// saves or update message_report table
messageRepository.save(message);
}
I'm receiving a stack trace in log files when testing my ZooKeeperFetcher class. I'm quite sure that the problem lies in the fact
that CuratorFramework client is being closed before the pathChildrenCache instance. Is it possible for pathChildrenCache to detect and
call close() once curatorFramework was closed? I cannot simply add new close() -> {pathChildrenCache.close(); } method to ZooKeeperFetcher.
Simplified code:
public class ZooKeeperFetcher() {
private final CuratorFramework client;
private PathChildrenCache pathChildrenCache;
ZooKeeperFetcher(CuratorFramework client) {
this.client = client;
pathChildrenCache = new PathChildrenCache(client, '/', true);
PathChildrenCacheListener pathListener =
(client, event) -> /* handle event */;
}
/* this option is just not possible for me */
// public void close() {
// pathChildrenCache.close();
// }
}
And the test class:
public class TestZooKeeperFetcher {
private TestingServer zookeeperServer;
private final CuratorFramework client;
private ZooKeeperFetcher fetcher;
#Before
public void beforeEachTest() {
zookeeperServer = new TestingServer(true);
client =
CuratorFrameworkFactory.newClient(
zookeeperServer.getConnectString(), new RetryNTimes(10, 50));
client.start();
fetcher = ZooKeeperFetcher(client);
}
#After
public void afterEachTest() throws Exception {
client.close();
}
#Test
public void justDontThrowExceptionsTest() throws Exception {
}
}
I am having an issue getting an initial RPC call to load data when the module is loaded.
I am adapting code from here and here.
The error that if fails on is a null pointer, and it behaves as if it is not even making the RPC call at all, since neither debug messages inside of the RPC appear in the test console in Eclipse.
The MenuItems object is an ArrayList < ArrayList < String > > object that implements IsSerializable and has a SerializableWhiteList entry as per this SO answer. This object is generated in an RPC RemoteServiceServlet.
The console also references the line
History.fireCurrentHistoryState();
in AppController.java (almost identical to the GWT Contacts example)
Ideas on why/where/how this is going astray? Any other implementation examples of initial RPC calls would be great also.
public class MVPtest implements EntryPoint {
MenuItems mItems;
public void onModuleLoad() {
MainServiceAsync rpcService = GWT.create(MainService.class);
System.out.println("Inside of mod load. rpcService = " + rpcService.toString());
rpcService.getMenuItems(new AsyncCallback<MenuItems>() {
public void onFailure(Throwable caught) {
System.out.println("I failed...");
caught.printStackTrace();
}
public void onSuccess(MenuItems result) {
System.out.println("I got the menuitems.");
mItems = result;
}
});
HandlerManager eventBus = new HandlerManager(null);
AppController appViewer = new AppController(rpcService, eventBus, mItems);
appViewer.go(RootLayoutPanel.get());
}
}
The rpcService debug message yields a non-null:
Inside of mod load. rpcService = com.******.******.test.client.MainService_Proxy#4f07f3b5
This statement is dangerous:
AppController appViewer = new AppController(rpcService, eventBus, mItems);
because your code on the client side will be executed without witing for the response of your call.
Something like this should work:
public class MVPtest implements EntryPoint {
MenuItems mItems;
public void onModuleLoad() {
MainServiceAsync rpcService = GWT.create(MainService.class);
System.out.println("Inside of mod load. rpcService = " + rpcService.toString());
rpcService.getMenuItems(new AsyncCallback<MenuItems>() {
public void onFailure(Throwable caught) {
System.out.println("I failed...");
caught.printStackTrace();
}
public void onSuccess(MenuItems result) {
System.out.println("I got the menuitems.");
mItems = result;
HandlerManager eventBus = new HandlerManager(null);
AppController appViewer = new AppController(rpcService, eventBus, mItems);
appViewer.go(RootLayoutPanel.get());
}
});
}
}
I'm working on a GWT project and have several void remote services that seem to execute just fine, but on the client side, end up firing the onFailure() method. No exceptions are thrown anywhere, and the expected behavior is observed on the backend. I have no idea what could be going wrong. Here is the relevant code:
Interfaces and implementation...
#RemoteServiceRelativePath("DeleteSearchService")
public interface DeleteSearchService extends RemoteService {
/**
* Utility class for simplifying access to the instance of async service.
*/
public static class Util {
private static DeleteSearchServiceAsync instance;
public static DeleteSearchServiceAsync getInstance(){
if (instance == null) {
instance = GWT.create(DeleteSearchService.class);
}
return instance;
}
}
public void delete(SearchBean search);
}
public interface DeleteSearchServiceAsync {
public void delete(SearchBean bean, AsyncCallback<Void> callback);
}
public class DeleteSearchServiceImpl extends RemoteServiceServlet implements DeleteSearchService {
private static final long serialVersionUID = 1L;
#Override
public void delete(SearchBean search) {
try {
Connection conn = SQLAccess.getConnection();
String sql = "DELETE FROM `searches` WHERE `id`=?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, search.getSearchId());
ps.execute();
sql = "DELETE FROM `searchsourcemap` WHERE `search-id` = ?";
ps = conn.prepareStatement(sql);
ps.setInt(1, search.getSearchId());
ps.execute();
return;
} catch (Exception e) {
// TODO Log error
e.printStackTrace();
}
}
}
Calling code...
private class DeleteListener implements ClickListener {
public void onClick(Widget sender) {
DeleteSearchServiceAsync dss = DeleteSearchService.Util.getInstance();
SearchBean bean = buildBeanFromGUI();
dss.delete(bean, new AsyncCallback<Void>(){
//#Override
public void onFailure(Throwable caught) {
// TODO log
SearchNotDeleted snd = new SearchNotDeleted();
snd.show();
}
//#Override
public void onSuccess(Void result) {
SearchDeleted sd = new SearchDeleted();
sd.show();
searchDef.getParent().removeFromParent();
}
});
}
}
I know I'm a jerk for posting like 500 lines of code but I've been staring at this since yesterday and can't figure out where I'm going wrong. Maybe a 2nd set of eyes would help...
Thanks,
brian
LGTM I'm afraid.
Are you using the hosted mode or a full-fledged browser? You can try switching and see if it helps.
Also, it might help listening to that //TODO and perform a GWT.log when onFailure is invoked.