I'm working with Grails 2.5.6.
I have a list of tasks that previously were executed in series and needed to reference a "lang" attribute I have on the session.
Now from the controller I call a class that creates threads, one per each tasks to accelerate the execution. After I added the threads, this error started to appear when the code tries to access the session:
No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the o
riginally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outs
ide of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
I believe there is something that needs to be setup in the threads I create to be able to access the request/session, but couldn't find any documentation.
The way the session is accessed is:
RequestContextHolder.currentRequestAttributes().session.lang
This worked OK before adding the threads.
Any ideas of what I need to do for that line of code to work on a new thread?
BTW I tried two ways of creating the threads, the classic Thread.start / treads*.join() and using grails.async.Promises (http://docs.grails.org/2.5.6/guide/async.html). On both I get the same error message.
I am also gone through the same issue while the params object passing to the thread run() method from controller,
The objects like, params, request and response don't have the longer reference when we pass them to thread, so we need to save that in another variable , what I did as follows,
def paramsData = params // you can declare other objects like request and eesponse
Now you can pass variable paramsData to your thread.
You can try add requestContext listener in your web.xml and reset app as follows,
<web-app> .... <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <listener> <listener-class> org.springframework.web.context.request.RequestContextListener </listener-class> </listener> .... </web-app>
Related
I want my Rest Controller POST Endpoint to only allow one thread to execute the method and every other thread shall get 429 until the first thread is finished.
#ResponseStatus(code = HttpStatus.CREATED)
#PostMapping(value ="/myApp",consumes="application/json",produces="application/json")
public Execution execute(#RequestBody ParameterDTO StartDateParameter)
{
if(StartDateParameter.getStartDate()==null) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
}else {
if(Executer.isProcessAlive()) {
throw new ResponseStatusException(HttpStatus.TOO_MANY_REQUESTS);
}else {
return Executer.execute(StartDateParameter);
}
}
}
When I send multithreaded requests, every request gets 201. So I think the requests get in earlier than the isAlive() method beeing checked. How can I change it to only process the first request and "block" every other?
Lifecycle of a controller in spring is managed by the container and by default, it is singleton, which means that there is one instance of the bean created at startup and multiple threads can use it. The only way you can make it single threaded is if you use a synchronized block or handle the request call through an Executor service. But that defeats the entire purpose of using spring framework.
Spring provides other means to make your code thread safe. You can use the #Scope annotation to override the default scope. Since you are using a RestController, you could use the "request" scope (#Scope("request")), which creates a new instance to process your every http request. Doing it this way will make ensure that only 1 thread will be accessing your controller code at any given time.
I have a quarkus application with an async endpoint that creates an entity with default properties, starts a new thread within the request method and executes a long running job and then returns the entity as a response for the client to track.
#POST
#Transactional
public Response startJob(#NonNull JsonObject request) {
// create my entity
JobsRecord job = new JobsRecord();
// set default properties
job.setName(request.getString("name"));
// make persistent
jobsRepository.persist(job);
// start the long running job on a different thread
Executor.execute(() -> longRunning(job));
return Response.accepted().entity(job).build();
}
Additionally, the long running job will make updates to the entity as it runs and so it must also be transactional. However, the database entity just doesn't get updated.
These are the issues I am facing:
I get the following warnings:
ARJUNA012094: Commit of action id 0:ffffc0a80065:f2db:5ef4e1c7:0 invoked while multiple threads active within it.
ARJUNA012107: CheckedAction::check - atomic action 0:ffffc0a80065:f2db:5ef4e1c7:0 commiting with 2 threads active!
Seems like something that should be avoided.
I tried using #Transaction(value = TxType.REQUIRES_NEW) to no avail.
I tried using the API Approach instead of the #Transactional approach on longRunning as mentioned in the guide as follows:
#Inject UserTransaction transaction;
.
.
.
try {
transaction.begin();
jobsRecord.setStatus("Complete");
jobsRecord.setCompletedOn(new Timestamp(System.currentTimeMillis()));
transaction.commit();
} catch (Exception e) {
e.printStackTrace();
transaction.rollback();
}
but then I get the errors: ARJUNA016051: thread is already associated with a transaction! and ARJUNA016079: Transaction rollback status is:ActionStatus.COMMITTED
I tried both the declarative and API based methods again this time with context propagation enabled. But still no luck.
Finally, based on the third approach, I thought keeping the #Transactional on the Http request handler and leaving longRunning as is without declarative or API based transaction approaches would work. However the database still does not get updated.
Clearly I am misunderstanding how JTA and context propagation works (among other things).
Is there a way (or even a design pattern) that allows me to update database entities asynchronously in a quarkus web application? Also why wouldn't any of the approaches I took have any effect?
Using quarkus 1.4.1.Final with ext: [agroal, cdi, flyway, hibernate-orm, hibernate-orm-panache, hibernate-validator, kubernetes-client, mutiny, narayana-jta, rest-client, resteasy, resteasy-jackson, resteasy-mutiny, smallrye-context-propagation, smallrye-health, smallrye-openapi, swagger-ui]
You should return an async type from your JAX-RS resource method, the transaction context will then be available when the async stage executes. There is some relevant documentation in the quarkus guide on context propagation.
I would start by looking at the one of the reactive examples such as the getting started quickstart. Try annotating each resource endpoint with #Transactional and the async code will run with a transaction context.
I need to inject a callContext object as thread Local in spring integration flow. A traceId which is received in jms header should be extracted n set in the callContext object so that it gets printed in log which is configured at project level.
IntegrationFlows.from(Jms.messageDrivenChannelAdapter(connectionFactory).destination(topicName))
.log(INFO, m-> “message received for: + ((Order)m.getPayload()).getOrderId())
.handle(orderService)
.get();
You can just do it in your orderService, or add another service just before it.
I would say a Function for log() operator provides you full control over what you would like to log in the message. Of course, also avoiding overhead with the ThreadLocal. But if you still would like to use it, I would suggest a .wireTap() before that log(), so you can store a value in your ThreadLocal (MDC?) without effecting the main flow.
Only the problem that you have to remember to clean that callContext somehow to avoid thread local pollution.
Scenario: I have 3 spring cloud streaming apps
1'st: unmarshalls XML payload into JAXB object
2'nd: Converts JAXB payload into our domain POJO
3'rd: Validate domain object
I am trying to test the 3'rd app. I have included the 1'st and 2'nd applications as test dependencies. I have added:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-test-support</artifactId>
<scope>test</scope>
</dependency>
Now I have about 20 xml files with various validation scenario's. The first test works fine. I am able pick up the expected message of the channel using:
final Message<PaymentInstruction> mceMessage =
(Message<PaymentInstruction>) collector.forChannel(
validationBindings.mce()).take();
The 2'nd test that is run is where I have an issue. The test just sits at 'take'.
I have done some digging in the spring-integration-core-4.3.8.jar and have traced the issue to org.springframework.integration.dispatcher.AbstractDispatcher:
#Override
public synchronized boolean addHandler(MessageHandler handler) {
Assert.notNull(handler, "handler must not be null");
Assert.isTrue(this.handlers.size() < this.maxSubscribers, "Maximum subscribers exceeded");
boolean added = this.handlers.add(handler);
if (this.handlers.size() == 1) {
this.theOneHandler = handler;
}
else {
this.theOneHandler = null;
}
return added;
}
There is a handler that was added for the first test, so it assigns null to 'this.theOneHandler'
My options are:
Refactor the code in the other 2 projects so that I can do the unmarshalling and creating of my domain object without the need for the spring cloud app code
I can create an individual unit test class per test case, however I'd rather not go this route as the startup time for spring boot will be high that will be multiplied by the number of test cases
Do I have some missing configuration that would allow me to have these multiple handlers or am I breaking the way I want to use spring cloud streaming?
Environment:
Java 8 Update 131
org.springframework.cloud:spring-cloud-dependencies:Dalston.RELEASE
org.springframework.boot:spring-boot-dependencies:1.5.2.RELEASE
theOneHandler is a dispatching optimization used when a channel has only one subscriber.
It sounds like you are binding all your services to the same channel, which is not what you want.
Bottom line is you can't do what you are trying to do because each of the services are using the same channel name (presumably input).
You would need to load each service in a separate application context and wire them together with bridges.
EDIT
You could also test them using an aggregated application.
Anyone experiencing the error messages for failed logins not appearing?
I am upgrading a grails 1.3.7 app to grails 2.1.1 and I have 2 issues with the spring security core functionality.
First, if I try an invalid login the auth fails but there is no error message just {} in the flash message.
Second, I was using a method like this to get the current count of active sessions. It no longer is accurate, as it just increases and doesn't recognize a logout.
def getCurrentSessionCount(){
def sessioncount = 0
sessionRegistry.getAllPrincipals().each{
sessioncount += sessionRegistry.getAllSessions(it, false).size()
}
return sessioncount;
}
Okay well this was a difference in the LoginController how the error messages were getting populated. In 1.3.7 and previous security plugin the code looks like:
msg = SpringSecurityUtils.securityConfig.errors.login.expired
but for 2.1.1 and the upgraded spring security plugin 1.2.7.3 the code needs to use the context like:
msg = g.message(code: "springSecurity.errors.login.disabled")
The session count has to do with a modification to the web.xml that you need to make to add the session listener, however in the new spring 3.0 it was moved so the new entry should look like:
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>