I need to start a variable number of threads which in turn each start a varying number of threads (i.e. i threads where the Ith thread needs to start Ki threads) in a spring application.
assuming each of the "I threads" contains an inner class which is autowired how will I generate those instances?
So I have an A bean which needs to somehow generate I instances of a bean which needs to be spring managed to satisfy its dependencies.
I've written a short sample code of what I think is the base for my solution and I've marked the code I'm not sure how to write by ???:
#Component
public class MasterOrchestrator {
public void do(List<DataObjWrapper> list){
ExecutorService es = Executors.newFixedThreadPool(list.size());
for (DataObjWrapper dataObjWrapper : list){
es.submit(???);
}
}
}
#Component
public class ThreadWorkerI implements Runnable{
private int numThreadsForMessageType;
private int numRunsForMessageType;
private DataObj dataObj;
public ThreadWorkerI(int numThreadsForMessageType, int numRunsForMessageType, DataObj dataObj){
this.numThreadsForMessageType = numThreadsForMessageType;
this.numRunsForMessageType = numRunsForMessageType;
this.dataObj = dataObj;
}
#Autowired
private JmsTemplate jmsTemplate;
public void run(){
ExecutorService es = Executors.newFixedThreadPool(numThreadsForMessageType);
for (int i=0;i<numRunsForMessageType;i++){
es.submit(new ActualWorker(i));
}
}
private class ActualWorker implements Runnable{
private int numRun;
private ActualWorker(int numRun){
this.numRun = numRun;
}
public void run(){
//send message using the jmsTemplate the dataObj and numRun
}
}
}
DatObjWrapper contains amongst other members the numThreadsForMessageType, numRunsForMessageType and dataObj.
You can use #Configurable annotation to let Spring inject dependencies into your workers - even the one's that are not managed explicitly by the Spring container.
Instead of starting your own threads it is better to use thread pool or Spring's task executor abstraction. Then your tasks can be Spring beans or manually instantiated.
How about passing a reference to the MasterOrchestrator or the ThreadWorker into the Runnable's constructor? Then you can put all the configuration into the #Component class.
For example:
private class ActualWorker implements Runnable{
private int numRun;
private ActualWorker(ThreadWorkerI owner, int numRun){
this.numRun = numRun;
}
public void run(){
//send message using owner.jmsTemplate, owner.dataObj and numRun
}
}
Related
I am new to Dropwizard and Hibernate.
Currently I am working on an application where I need to use AsyncThreadPool for performing some time consuming operations from my main thread which needs to send a response right away.
In the synchromous flow the operations are working fine because my listener has #UnitOfWork annotation in place. But in the threadpool spawned thread I am getting "No session currently bound to execution context" error every time.
I tried #UnitOfWork annotation on thread class as well as the run() method, as the documentation says that I have to use this annotation from the resource accessing the instance.
Here is my runnable class.
public class CallbackTask implements Runnable{
Snapshot baseSnapshot;
ProcessorResponse processorResponse;
Job job;
ElasticSearchDAO esDao;
OrchestratorJobService orchestratorJobService;
Snapshot snapshot;
RestoreHelper restoreHelper;
String indexName;
public CallbackTask(Snapshot baseSnapshot, ProcessorResponse processorResponse, Job job, ElasticSearchDAO esDao, OrchestratorJobService orchestratorJobService, Snapshot snapshot, RestoreHelper restoreHelper, String indexName) {
this.baseSnapshot = baseSnapshot;
this.processorResponse = processorResponse;
this.job = job;
this.esDao = esDao;
this.orchestratorJobService = orchestratorJobService;
this.snapshot = snapshot;
this.restoreHelper = restoreHelper;
this.indexName = indexName;
}
#Override
#Transactional
public void run() {
int retryCount = job.getRetrialCount()==null ? 0: job.getRetrialCount();
if(retryCount< JOB_RETRY_COUNT){
job.setRetrialCount(++retryCount);
//orchestratorJobService.runConfig(job.getConfigId(), null);
}else{
snapshot.setSoftDelete(true);
}
orchestratorJobService.persistData(job, snapshot);
}
Thanks in advance for any help.
Make sure that you're using a managed ExecutorService (i.e. do not create it yourself, use the built-in methods):
public class MyApplication extends Application<MyConfiguration> {
#Override
public void run(MyConfiguration configuration, Environment environment) {
ExecutorService executorService = environment.lifecycle()
.executorService(nameFormat)
.maxThreads(maxThreads)
.build();
ScheduledExecutorService scheduledExecutorService = environment.lifecycle()
.scheduledExecutorService(nameFormat)
.build();
}
}
#UnitOfWork uses the current session context strategy, so you need to put a session to the current thread context
Dropwizard #UnitOfWork with asynchronous database call
I am new to Spring and have only scratched the surface of what can be done with it.
I have a situation where I need to set up a recurring task using the #Scheduled annotation. The rate is specified as a member field in an object that is passed to the class encapsulating the method representing the task.
I've used the mechanism that allows for accessing the configuration or environment, e.g. #Scheduled(fixedRateString = "${some.property:default}"); this works great.
What I don't know how to do is insert the value from an object into the #Scheduled.
For example:
class MyClass {
private MyObject myObj;
public MyClass(MyObject myObj) {
this.myObj = myObj;
}
#Scheduled(fixedRateString = "${myObj.rate:5000}")
private void someTask() {
...
}
}
The code above, of course, does not work, I'm just giving an example of what I'm trying to do.
Any suggestions would be appreciated.
Yes you can use the #Scheduled annotation to do that with a SpEL expression (available on the #Scheduled annotation since Spring 4.3.x). Here's an example:
#Slf4j
#Configuration
#EnableScheduling
public class ExampleClass {
static class ScheduleCalculator {
public String calc() {
return "5000";
}
}
#Bean("scheduleCalculator")
public ScheduleCalculator createScheduleCalculator() {
return new ScheduleCalculator();
}
#Scheduled(fixedRateString = "#{scheduleCalculator.calc()}")
public void someTask() {
log.info("Hello world");
}
}
However, just because you can do it like this doesn't mean you necessarily should.
Your code may be easier to follow to folks that have to maintain it in the future if you use the spring task scheduler plus you get control of the thread pool used for scheduling instead of relying on the shared executor that all #Scheduled tasks get lumped into.
Unfortunately the spring bean creation process will not read local variables like that.
You can use the Spring TaskScheduler class.
Essentially you just have to define a thread pool that you will use to run the scheduled tasks (as a bean) and run taskScheduler.schedule(runnable, new CronTrigger("* * * * *")). There is a detailed example here:
https://www.baeldung.com/spring-task-scheduler
You can do like follow:
#Component
#ConfigurationProperties(prefix = "my.obj")
public class MyObject {
private String cronExecExpr = "*/5 * * * * *";
// getter and setter
}
class MyClass {
private MyObject myObj;
public MyClass(MyObject myObj) {
this.myObj = myObj;
}
#Scheduled(cron = "${my.obj.cron-exec-expr:*/5 * * * * *}")
private void someTask() {
...
}
}
As you can see her : https://www.baeldung.com/spring-scheduled-tasks
You can do that like follow :
A fixedDelay task:
#Scheduled(fixedDelayString = "${fixedDelay.in.milliseconds}")
A fixedRate task:
#Scheduled(fixedRateString = "${fixedRate.in.milliseconds}")
A cron expression based task:
#Scheduled(cron = "${cron.expression}")
Is there any way to get the number and some identification information of already created entities of particular Prototype-bean in Spring application?
Addition. In our project we have more then 400 prototype-beans and I would like to trace the state what beans were created during execution and the number of entities of each type.
I have found a way to see the actual picture about created prototype-beans.
I use free VisualVM memory profiler.
In the Sampler tab you can see all instances of created classes including singleton and prototype beans.
You'll see the names of your own packages and classes. In this case:
prototype is a package with my prototype-beans.
singleton is a package with my singleton-beans.
newclasses is a package with classes that I created by new operator.
Also after the garbage collector will clean up the memory you will see the result here.
you can do it by Publish and Listen Application Events.
create you own event.
when prototype bean was created send event from it.
create count ApplicationListener , and listen to income creation event.
here is example
Spring – Publish and Listen Application Events
Spring does not manage the complete lifecycle of a prototype bean: the container instantiates, configures, decorates and otherwise assembles a prototype object, hands it to the client and then has no further knowledge of that prototype instance.
Simple variant :
public class PrototypeCreationEvent extends ApplicationEvent {
private String beanName;
public PrototypeCreationEvent(Object source , String beanName) {
super(source);
this.beanName = beanName;
}
public String getBeanName(){
return beanName;
}
}
public class PrototypeCreationListener implements ApplicationListener<PrototypeCreationEvent> {
private ConcurrentMap<String,AtomicInteger> prototypeCreationStatistic = new ConcurrentHashMap<>();
//or from guava AtomicLongMap prototypeCreationStatistic = AtomicLongMap.create();
#Override
public void onApplicationEvent(PrototypeCreationEvent event) {
prototypeCreationStatistic.computeIfAbsent(event.getBeanName() , k->new AtomicInteger(0)).incrementAndGet();
System.out.println(event);
}
public ConcurrentMap<String,AtomicInteger> getPrototypeCreationStatistic(){
return prototypeCreationStatistic;
}
}
public abstract class PrototypeCreationPublisher implements BeanNameAware , ApplicationEventPublisherAware ,InitializingBean {
private String beanName;
private ApplicationEventPublisher applicationEventPublisher;
#Override
public void setBeanName(String name) {
this.beanName = name;
}
#Override
public void afterPropertiesSet() throws Exception {
System.out.println();
}
#Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
#PostConstruct //or use interface InitializingBean
public void sendEventAfterCreation() throws Exception {
applicationEventPublisher.publishEvent(new PrototypeCreationEvent(this , beanName));
}
}
#Component(value = BeanDefinition.SCOPE_PROTOTYPE)
public class PrototypeA extends PrototypeCreationPublisher{
}
#Component(value = BeanDefinition.SCOPE_PROTOTYPE)
public class PrototypeB extends PrototypeCreationPublisher{
}
example :
PrototypeA prototypeA1 = context.getBean(PrototypeA.class);
PrototypeA prototypeA2 = context.getBean(PrototypeA.class);
PrototypeA prototypeA3 = context.getBean(PrototypeA.class);
PrototypeB prototypeB1 = context.getBean(PrototypeB.class);
PrototypeCreationListener statistic = context.getBean(PrototypeCreationListener.class);
statistic.getPrototypeCreationStatistic().entrySet().forEach(s->{
System.out.println(s.getKey() + " count = "+s.getValue());
});
result :
PrototypeB count = 1
PrototypeA count = 3
I am new in spring and have to use spring annotations all through the project. I need to create a list of beans. I do not have option to use context.getBean("..") from the class where I have to create the list.
The problem is :
I have 3 classes: Processor, Reader, Writer. I have to create a list of writers inside the processor class.
This is what I am looking for : ( trying to #Autowire 'RoxourReader readerThread' and 'List writerThreads' but don't know how determine the size of the list and need to add the name as well)
package company.online.Roxour.api.operation;
{
#Component
#Scope("singleton")
public class RoxourProcessor
{
.........
private int PAYLOAD_SIZE;
private int MAX_READER_THREADS;
private int MAX_WORKER_THREADS;
#Autowired
ApplicationEnvironment applicationEnvironment;
#Autowired
RoxourUtil util;
//I wish to have something like this
#Autowired
RoxourReader readerThread
//I wish to have something like this
#Autowired
List<RoxourWriter> writerThreads;
#PostConstruct public void initialize()
{
PAYLOAD_SIZE = applicationEnvironment.getPayloadSize();
MAX_READER_THREADS = applicationEnvironment.getMaxReaderThreads();
MAX_WORKER_THREADS = applicationEnvironment.getMaxWorkerThreads();
}
..............
}
}
Reader class looks like :
package company.online.Roxour.api.operation;
{
#Component
#Scope("prototype")
public class RoxourReader extends Thread
{
.........
#Autowired
ApplicationEnvironment applicationEnvironment;
public RoxourReader( String name)
{
this.name = name;
}
..............
}
}
And the writer class looks like :
package company.online.Roxour.api.operation;
{
#Component
#Scope("prototype")
public class RoxourWriter extends Thread
{
.........
#Autowired
ApplicationEnvironment applicationEnvironment;
public RoxourWriter( String name)
{
this.name = name;
}
..............
}
}
context.xml has:
<!-- Scans within the base package of the application for #Components to configure as beans -->
<context:component-scan base-package="company.online.Roxour.api"/>
According to current implementation, this is the way we are creating the treads:
private void createAllThreads()
{
readerThread = new RoxourReader( "Reader " + 1 );
writerThreads= new RoxourWriter[ MAX_WORKER_THREADS ];
for ( int i = 0; i < MAX_WORKER_THREADS; i++ )
{
writerThreads[ i ] = new RoxourWriter( "Uploader " + i);
}
}
Is this possible? Please advise me a different approach with annotations otherwise.
Thanks
When you use a IoC framework like Spring, you leave the task of bean creation to Spring. So you shouldn't use new keyword, this is made by Spring automatically.
Instead you should get your beans through context.getBean("beanname") or
injecting the bean with #autowired.
Here there is an example or Spring with threads (There is 3 good examples)
http://www.mkyong.com/spring/spring-and-java-thread-example/
And here there is the definition of task executors.
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html
To begin with,
public class RoxourReader extends Thread
{
is not a good idea, because you are not extending the Thread behavior. Instead make it
public class RoxourReader implements Runnable
{
and when you use the keyword new to create an object, then Spring is not actually managing it.
So change the lines
new RoxourReader... &
new RoxourWriter
to Autowired (or) getBeans methods like
private void createAllThreads()
{
readerThread = getReaderBean("readerBeanName");
writerThreads= new Runnable[MAX_WORKER_THREADS];
for ( int i = 0; i < MAX_WORKER_THREADS; i++ )
{
writerThreads[ i ] = getWriterBean("Uploader " + i);
}
}
And your getBeans methods would look like,
public Runnable getReaderBean(){
Runnable obj= applicationContext.getBean("RoxourReader");
return obj;
}
public Runnable getWriterBean(){
Runnable obj= applicationContext.getBean("RoxourWriter");
return obj;
}
Since your scope is Prototype for both reader and writer beans already, you will get a new bean instance.
The tasks submitted uses resource beans from a spring container. Are the methods in the beans thread safe when accessed by concurrent threads of a executor service?
They aren't thread-safe by definition. If your Spring beans are immutable, stateless or properly synchronized (99% of the cases) they are thread safe. Here are few examples of thread-safe Spring beans:
Only final fields:
public class ImmutableService {
private final Dependency dep;
#Autowired
public StatelessService(Dependency dep) {
this.dep = dep;
}
public Foo foo() {
return dep.foo();
}
}
Field is modified only during creation, effectively final:
public class EffectivelyImmutableService {
#Autowired
private final Dependency dep;
public Foo foo() {
return dep.foo();
}
}
No state, typical utility class:
public class StatelessService {
public Foo foo() {
return new Foo();
}
}
Non-atomic operations are synchronized:
public class SynchronizedService {
private int counter;
public synchronized Foo foo() {
return new Foo(counter++);
}
}
AtomicInteger to avoid explicit synchronization (field is final, but the object isn't):
public class AtomicService {
private final AtomicInteger counter = new AtomicInteger();
public Foo foo() {
return new Foo(counter.incrementAndGet());
}
}
Note that this rule applies to all use-cases, not only to tasks using Spring beans in thread pool. For instance if your servlets/controllers use Spring beans, they have to be thread safe as well.
If you were to manually start two threads accessing these beans, would the access be threadsafe then? An executor service does no magic and does not change anything about the code running in its threads. If accessing the beans is not threadsafe from two manually started threads, it's not threadsafe when the code is executed by threads managed by an Executor either.