Get queue size of ThreadPoolTaskExecutor and add to queue in Spring boot - spring

I have the following class which has multiple custom ThreadPoolTaskExecutors I am showing it with one in this example.
#Configuration
#EnableAsync
public class ExecutorConfig {
#Bean(name = "streetCheckerExecutor")
public Executor getStreetAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(50);
executor.setQueueCapacity(1000000);
executor.setThreadNamePrefix("streetCheckerExecutor-");
executor.initialize();
return executor;
}
}
I have the following class which gets content from the database, I want to be able to check the queue size of streetCheckerExecutor and if it's less than a certain number, to add the content to the queue
#Component
public class StreetChecker {
#Autowired
StreetRepository streetRepository;
#Autowired
StreetCheckService streetChecker;
#EventListener(ApplicationReadyEvent.class)
public void checkStreets() {
try {
List<Street> streetList = streetRepository.getStreets();
for (int i = 0; i < streetList.size(); i++) {
streetChecker.run(streetList.get(i));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("---------------------");
}
}
}
And below is the worker class
#Component
public class StreetCheckService {
#Async("streetCheckerExecutor")
public void run(Content content) {
try {
//do work
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
}
I am working with a lot of data and I don't want to grab everything from the database every time, but I want to check the queue size of streetCheckerExecutor and if it's less than a number, I want to get more content from the database and add it to the streetCheckerExecutor queque
Below is how I'm thinking I can do it by converting the above checkStreets to the one below
#EventListener(ApplicationReadyEvent.class)
public void checkStreets() {
while (true) {
try {
// check the queue size of streetCheckerExecutor
// if less than a number
// add to the queue
// else keep waiting and will try again in X minutes
} catch (Exception e) {
} finally {
try {
Thread.sleep(1000 * 60);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
But how would I be able to get the size of the queue in the checkStreets() method?

You can just autowire in your ThreadPoolTaskExecutor and get the queue with getThreadPoolExecutor().getQueue().
#Autowire
#Qualifier("streetCheckerExecutor")
private Executor streetExecutor;
#EventListener(ApplicationReadyEvent.class)
public void checkStreets() {
while (true) {
try {
final BlockingQueue<Runnable> queue = streetExecutor.getThreadPoolExecutor().getQueue();
if(queue.size() <= 5) {
queue.add(() -> {
final List<Street> streetList = streetRepository.getStreets();
streetList.forEach(street -> {
streetChecker.run(street);
});
});
}
} catch (Exception e) {
} finally {
try {
Thread.sleep(1000 * 60);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
i'm not sure this is what you meant, but something like this maybe.

Related

Parameterize Test in SpringBoot

I have an ExceptionTest class where I store the Tests for each of the classes. I have quite a few methods where I am repeating the same structure.
public class ExceptionTest {
#Test
void conversionException() {
assertThrows(ConversionException.class, () -> {
try {
throw new ConversionException();
} catch (QOException ex) {
assertEquals("Error converting", ex.getMessage());
assertEquals(417 /* FAILED */, ex.getHttpStatus());
assertEquals(ErrorCodes.DOCUMENT_ERROR, ex.getCode());
throw ex;
}
});
}
#Test
void userException() {
assertThrows(UserException.class, () -> {
try {
Integer maxUsers = 5;
throw new UserException(maxUsers);
} catch (QOException ex) {
Integer maxUsers = 5;
assertEquals("Excedido "+ maxUsers +" disp", ex.getMessage());
assertEquals(403 /* FORBIDDEN */, ex.getHttpStatus());
assertEquals(ErrorCodes.USERS, ex.getCode());
throw ex;
}
});
}
}
From what I have read in Spring you can use the #ParameterizedTest annotation in a separate class and call that class from each Test method, and collect it from the method parameterized with the #MethodSource annotation.
This is the code I am looking for:
#ParameterizedTest
#MethodSource("stringProvider")
void testWithExplicitLocalMethodSource(String argument) {
assertNotNull(argument);
}
The problem is that I do not apply it to the classes I have in Test. How do I have to create the method in a separate class to apply the structure to all the Tests that are in the ExceptionTest class?
Your question seems familiar to an article posted by Baeldung.com; where they gave this as example:
class StringsUnitTest {
#ParameterizedTest
#MethodSource("com.baeldung.parameterized.StringParams#blankStrings")
void isBlank_ShouldReturnTrueForNullOrBlankStringsExternalSource(String input) {
assertTrue(Strings.isBlank(input));
}
}
public class StringParams {
static Stream<String> blankStrings() {
return Stream.of(null, "", " ");
}
}

How to fix 'No way to dispatch this command to Redis Cluster because keys have different slots' in Spring

I need to use Redis Cluster in Spring. But I'm getting the following error when I use mget or del on a list of keys: 'No way to dispatch this command to Redis Cluster because keys have different slots'. Showing a part of my Component code using JedisCluster.
It works when I use single key operations but not with multiple keys.
/* Component Code */
public class RedisServiceManager {
#Value("${redis.hosts}")
String hosts;
#Autowired
JedisPoolConfig jedisPoolConfig;
private JedisCluster jedisCluster;
#PostConstruct
private void init() {
List<String> redisHosts = Arrays.asList(hosts.split(","));
Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();
redisHosts.forEach(redisHost -> {
jedisClusterNode.add(new HostAndPort(redisHost, 6379));
});
jedisCluster = new JedisCluster(jedisClusterNode, jedisPoolConfig);
}
// This works
public String getValueForKey(String key) {
try {
return jedisCluster.get(key);
} catch (Exception e) {
return null;
}
}
// This works
public void delKey(String cacheKey) {
try {
jedisCluster.del(cacheKey);
} catch (Exception e) {
}
}
// This doesn't work
public List<String> getValuesForAllKeys(String... keys) {
try {
return jedisCluster.mget(keys);
} catch (Exception e) {
return new ArrayList<>();
}
}
// This doesn't work
public void delAllKeys(String... keys) {
try {
jedisCluster.del(keys);
} catch (Exception e) {
}
}
}
Can someone help with this?
This is not a bug or an issue, but is the way how redis cluster works. You can find more details in the cluster documentation. But don't worry: there is a "trick": you can use hash as described here

TcpSocketClient- UnhandledException when I try read a response inside of a Task that not arrived yet

I'm using this library(https://github.com/rdavisau/sockets-for-pcl) to communicate with a TCP Server, that sends me when a event was generated, then, I have to verify all the time if the TCP Server sent to me a event, but if I try read anything before the TCP Server sends me, it's thrown the UnhandledException, but it only happens if I read inside a Task, in the main thread it thrown a timeout exception, the exception that I expected to happen in Task.
Someone can help me? Thanks. below is my code.
public class CentralTcpService
{
#region ConnectTcpAsync
public async void ConnectTcpAsync()
{
try
{
_sockecClient = new TcpSocketClient();
await _sockecClient.ConnectAsync(Central.Ip, Central.Port);
_writter = new ExtendedBinaryWriter(_sockecClient.WriteStream);
_reader = new ExtendedBinaryReader(_sockecClient.ReadStream);
_writter.WriteString(EvenNotProtocol.MobileReceiverCommand);
_sockecClient.ReadStream.ReadTimeout = int.MaxValue;
EnableTcpService();
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
#endregion
#region TcpService
private void EnableTcpService()
{
_cancelationTcpService = new CancellationTokenSource();
new Task(StartService, _cancelationTcpService.Token, TaskCreationOptions.LongRunning).Start();
}
private void StartService()
{
while (!_cancelationTcpService.Token.IsCancellationRequested)
{
var ev = EvenNotProtocol.DeserializeEvent(_reader);
if (ev == null) continue;
_writter.WriteString(EvenNotProtocol.MobileOkCommand);
EventReceived?.Invoke(this, new CentralTcpEventArgs(ev));
}
}
}
public class EvenNotProtocol
{
public static Event DeserializeEvent(ExtendedBinaryReader reader)
{
try
{
reader.SkipBytes(1);
.....
}
catch (IOException e)
{
return null;
}
}
}

RxJava cache last item for future subscribers

I have implemented simple RxEventBus which starts emitting events, even if there is no subscribers. I want to cache last emitted event, so that if first/next subscriber subscribes, it receive only one (last) item.
I created test class which describes my problem:
public class RxBus {
ApplicationsRxEventBus applicationsRxEventBus;
public RxBus() {
applicationsRxEventBus = new ApplicationsRxEventBus();
}
public static void main(String[] args) {
RxBus rxBus = new RxBus();
rxBus.start();
}
private void start() {
ExecutorService executorService = Executors.newScheduledThreadPool(2);
Runnable runnable0 = () -> {
while (true) {
long currentTime = System.currentTimeMillis();
System.out.println("emiting: " + currentTime);
applicationsRxEventBus.emit(new ApplicationsEvent(currentTime));
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Runnable runnable1 = () -> applicationsRxEventBus
.getBus()
.subscribe(new Subscriber<ApplicationsEvent>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable throwable) {
}
#Override
public void onNext(ApplicationsEvent applicationsEvent) {
System.out.println("runnable 1: " + applicationsEvent.number);
}
});
Runnable runnable2 = () -> applicationsRxEventBus
.getBus()
.subscribe(new Subscriber<ApplicationsEvent>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable throwable) {
}
#Override
public void onNext(ApplicationsEvent applicationsEvent) {
System.out.println("runnable 2: " + applicationsEvent.number);
}
});
executorService.execute(runnable0);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
executorService.execute(runnable1);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
executorService.execute(runnable2);
}
private class ApplicationsRxEventBus {
private final Subject<ApplicationsEvent, ApplicationsEvent> mRxBus;
private final Observable<ApplicationsEvent> mBusObservable;
public ApplicationsRxEventBus() {
mRxBus = new SerializedSubject<>(BehaviorSubject.<ApplicationsEvent>create());
mBusObservable = mRxBus.cache();
}
public void emit(ApplicationsEvent event) {
mRxBus.onNext(event);
}
public Observable<ApplicationsEvent> getBus() {
return mBusObservable;
}
}
private class ApplicationsEvent {
long number;
public ApplicationsEvent(long number) {
this.number = number;
}
}
}
runnable0 is emitting events even if there is no subscribers. runnable1 subscribes after 3 sec, and receives last item (and this is ok). But runnable2 subscribes after 3 sec after runnable1, and receives all items, which runnable1 received. I only need last item to be received for runnable2. I have tried cache events in RxBus:
private class ApplicationsRxEventBus {
private final Subject<ApplicationsEvent, ApplicationsEvent> mRxBus;
private final Observable<ApplicationsEvent> mBusObservable;
private ApplicationsEvent event;
public ApplicationsRxEventBus() {
mRxBus = new SerializedSubject<>(BehaviorSubject.<ApplicationsEvent>create());
mBusObservable = mRxBus;
}
public void emit(ApplicationsEvent event) {
this.event = event;
mRxBus.onNext(event);
}
public Observable<ApplicationsEvent> getBus() {
return mBusObservable.doOnSubscribe(() -> emit(event));
}
}
But problem is, that when runnable2 subscribes, runnable1 receives event twice:
emiting: 1447183225122
runnable 1: 1447183225122
runnable 1: 1447183225122
runnable 2: 1447183225122
emiting: 1447183225627
runnable 1: 1447183225627
runnable 2: 1447183225627
I am sure, that there is RxJava operator for this. How to achieve this?
Your ApplicationsRxEventBus does extra work by reemitting a stored event whenever one Subscribes in addition to all the cached events.
You only need a single BehaviorSubject + toSerialized as it will hold onto the very last event and re-emit it to Subscribers by itself.
You are using the wrong interface. When you susbscribe to a cold Observable you get all of its events. You need to turn it into hot Observable first. This is done by creating a ConnectableObservable from your Observable using its publish method. Your Observers then call connect to start receiving events.
You can also read more about in the Hot and Cold observables section of the tutorial.

how to create a image slideshow for blackberry?

what i am trying to do is that on click of a button in screen1, i try push the screen2 repeatedly with different images and different Transition Context.
the code is as follows
public void fieldChanged(Field field, int context)
{
if(field==slideButton)
{
for(int i=0;i<bitmaps.length;i++)
{
slideScreen = new SliderScreen(bitmaps[i]);
UiApplication.getUiApplication().pushScreen(slideScreen);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
UiApplication.getUiApplication().popScreen(slideScreen);
}
}
}
}
Problem is that nothing appears.Is there any other way to achieve this..
Fixed version of your initial idea:
public void fieldChanged(Field field, int context) {
if (field==slideButton) {
final UiApplication app = UiApplication.getUiApplication();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < bitmaps.length; i++) {
final SliderScreen slideScreen =
new SliderScreen(bitmaps[i]);
app.invokeAndWait(new Runnable() {
public void run() {
app.pushScreen(slideScreen);
}
});
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
app.invokeAndWait(new Runnable() {
public void run() {
app.popScreen(slideScreen);
}
});
}
}
}).start();
}
}
Your code did not work because the UI thread was sleeping between push and pop, so it has no time/chance to start drawing the screen. Note I moved the entire action into a separate thread. So now the main UI thread has free time to actually make drawing.

Resources