I am new to Hystrix. I am trying to use it with Spring AOP. The following details what I am trying to achieve.
There is a "ServiceClass", into which some RestClient class is injected. I am using Spring. Now, I want to use Hystrix together with Spring AOP so that method calls to the RestClient from the ServiceClass could be made synchronously or asynchronously.
What I have done so far is as follows.
created a class "MyCommand" that extends HystrixCommand implements MethodInterceptor
implemented a method "execute(MethodInvocation m, String mode) in it as follows:
protected Object execute(MethodInvocation m, String mode){
this.mode = mode;
this.method = m;
return execute();}
in the (overridden method) "invoke"
public Object invoke(MethodInvocation m) throws throwable{
try{
execute(m,"Sync");
} catch(Exception e){
e.printStackTrace();
}
}
This "MyCommand" is being set as the AOP Interceptor for the "ServiceClass" in the spring-config file.
Now, the issue is; in my "Main" application when I retrieve the "ServiceClass" from the ClassPathXmlApplicationContext and invoke one method, it works fine. But if I try to invoke two of the methods of the "ServiceClass" it throws the following exception:
*java.lang.IllegalStateException: This instance can only be executed once. Please instantiate a new instance.*
Code snippet:
ServiceClass srvc = (ServiceClass) ctx.getBean("proxy");
srvc.getRequest();
srvc.postRequest();
I have spent almost three days trying to figure it out the cause and solution for this exception but without any good. Please help me get this right. What am I missing?
As always,
Thanks in advance
A HystrixCommand object can only be used once, because it contains useful state information after it is executed that can be used for further processing. For example, if you wanted to do special handling after the fact if the call to run() timed out, you could do the following:
public class MyHystrixCommand extends HystrixCommand<Object> { ... }
MyHystrixCommand command = new MyHystrixCommand();
command.execute();
if(command.isResponseTimedOut()){
//do post processing
}
If you could invoke execute() multiple times, especially from multiple threads as would happen if you had multiple consumers of your REST endpoint, you would have no way of knowing which invocation was the one that timed out when you queried the command for its state.
Related
I have some problems regarding Controller usage in Spring.
Preferably, I would like to keep the Controller methods small and simply use them to call a Service function as follows:
#Controller
class controllerClass {
#RequestMapping("/foo/")
public void foo(Model model) {
Data returnedData = fooServiceFunction();
model.addAttribute("data", returnedData);
}
}
#Service
class serviceClass {
fooServiceFunction() {
Data data = methodCall();
methodCall2();
methodCall3();
return data;
}
}
However, in practise I have found this implementation difficult because I have found myself needing to check if the methods called from within the fooServiceFunction() succeeded or failed. I have been returning a custom 'Status' class from these functions which is passed to the controller to signal if the methods have executed successfully and/or any errors that have occurred (validation errors, etc.).
Now, this is fine if I do not need to return any data. But if I want to return data from the Service function and pass it to the Controller, this would mean I would need to make a custom class for EVERY Controller method which would contain:
a) the data.
b) the success status
which just seems unreasonable.
I have considered just throwing Exceptions to indicate a failure, but this doesn't seem proper.
Is there a better way? What is the optimal way to handle these situations? Or should I just write fat Controller methods that implement more of the application/business logic?
Thank you.
I think the best approach would be to throw a custom exception and then use a class annotated with
#ControllerAdvice
to deal with that exception and make it return a ResponseEntity customized according to your needs. This way the line
return data;
will only occur if there are no exceptions
I am using Camel Timer component to read blobs from Azure storage container. A route is created which will poll for blobs every 10secs and is processed by the CloudBlobProcessor.
from("timer://testRoute?fixedRate=true&period=10s")
.to("azure-blob://storageAccountName/storageContainerName?credentials=#credentials")
.to(CloudBlobProcessor)
.to("mock:result");
I want to write a testcase by creating a mock endpoint something like this
MockEndpoint timerMockEndpoint = context.getEndpoint("timer://testRoute?fixedRate=true&period=10s", MockEndpoint.class);
But, I receive a below exception while creating the above mock endpoint.
java.lang.IllegalArgumentException: The endpoint is not of type:
class org.apache.camel.component.mock.MockEndpoint but is: org.apache.camel.component.timer.TimerEndpoint
Below is the code where I am trying to skip sending to the original endpoint
#Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new AdviceWithRouteBuilder() {
#Override
public void configure() throws Exception {
interceptSendToEndpoint("timer://testRoute?fixedRate=true&period=10s").skipSendToOriginalEndpoint()
.log("Original Batch Endpoint skipped")
.to("azure-blob://*")
.to(CloudBlobProcessor).to("mock:result");
from("timer://testRoute?fixedRate=true&period=10s").to("mock:result");
}
};
}
What I understand, we're trying to solve two different problems here:
MockEndpoint != TimerEndpoint
Interceptions
Answer to the first one is simple: MockEndpoints follow syntax mock:name. TimerEndpoint is a different endpoint and a totally different object. I don't know what you're aiming to do with the MockEndpoint here, but we just can't technically have a TimerEndpoint object as a MockEndpoint object. Why? Because that's how object oriented programming and Java work.
Let's take a look on the second problem. I've less than a year experience with Camel and I've only used interception once last year, but I hope I can guide you to some helpful direction.
The point of interception is to say "don't do that, do this instead". In this use case, it seems that we're only trying to skip sending a request to azure-blob endpoint. I'd try intercepting azure-blob://storageAccountName/storageContainerName?credentials=#credentials.
So instead of your interception, I'd try writing an interception like this:
interceptSendToEndpoint("azure-blob://storageAccountName/storageContainerName?credentials=#credentials")
.skipSendToOriginalEndpoint()
.log("Intercepted!");
In this case, instead of sending the request to azure-blob we intercept that request. We're telling Camel to skip the send to original endpoint, which means nothing will be sent to azure-blob://storageAccountName/storageContainerName?credentials=#credentials. Instead, we'll log "Intercepted!".
I am trying to get the FacesContext by calling FacesContext.getCurrentInstance() in the run() method of a Runnable class, but it returns null.
public class Task implements Runnable {
#Override
public void run() {
FacesContext context = FacesContext.getCurrentInstance(); // null!
// ...
}
}
How is this caused and how can I solve it?
The FacesContext is stored as a ThreadLocal variable in the thread responsible for the HTTP request which invoked the FacesServlet, the one responsible for creating the FacesContext. This thread usually goes through the JSF managed bean methods only. The FacesContext is not available in other threads spawned by that thread.
You should actually also not have the need for it in other threads. Moreover, when your thread starts and runs independently, the underlying HTTP request will immediately continue processing the HTTP response and then disappear. You won't be able to do something with the HTTP response anyway.
You need to solve your problem differently. Ask yourself: what do you need it for? To obtain some information? Just pass that information to the Runnable during its construction instead.
The below example assumes that you'd like to access some session scoped object in the thread.
public class Task implements Runnable {
private Work work;
public Task(Work work) {
this.work = work;
}
#Override
public void run() {
// Just use work.
}
}
Work work = (Work) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("work");
Task task = new Task(work);
// ...
If you however ultimately need to notify the client e.g. that the thread's work is finished, then you should be looking for a different solution than e.g. adding a faces message or so. The answer is to use "push". This can be achieved with SSE or websockets. A concrete websockets example can be found in this related question: Real time updates from database using JSF/Java EE. In case you happen to use PrimeFaces, look at
<p:push>. In case you happen to use OmniFaces, look at <o:socket>.
Unrelated to the concrete problem, manually creating Runnables and manually spawning threads in a Java EE web application is alarming. Head to the following Q&A to learn about all caveats and how it should actually be done:
Spawning threads in a JSF managed bean for scheduled tasks using a timer
Is it safe to start a new thread in a JSF managed bean?
I'm building an UI client that uses a service API that behind the scene uses Web services. One of the API services looks like this:
interface UserService {
List<User> findUsers(User loggedInUser, UserSearchParameters searchParameters, PagingParameters pagingParameters) throws AuthenticationFault, InvalidIndexFault;
void removeUser(User loggedInUser, User userToRemove) throws AutheticationFault;
void addUser(User loggedInUser, User newUser) throws AuthenticationFault;
}
The loggedInUser is the user on who's behalf the method is called. AuthenticationFault is a checked exception. There's like 20 of these service interfaces. What I would like to do is implement a facade that hides the loggedInUser parameters and AuthenticationFault exceptions. The facade implementation would call these methods with the user that is currently logged in the client.
I would also like to do some cleaning with the other checked exceptions too. As you can see there is a InvalidIndexFault exception that is thrown when client tries to retrieve page -1 but that is a programmer error and I don't want to have it as a checked exception.
Currently what I've done is always rethrow a RuntimeException for exceptions that I don't like, but if I later change my mind it's a lot of work changing that later. This also feels like code duplication. Other programmers have just swallowed exceptions and logged them which is totally horrible. Most of the time if there is an exception I want to bubble it up to error handler in the ui that displays an error.
There's been a few solutions that have come to my mind:
Java dynamic proxy
Code generation
I haven't gotten around to try out those solutions and figured I might as well ask here first. How do you suggest I would implement this? The environment is Java 6 and build tool is Maven 3 if that helps.
PS. If you answer this, please say more than "pick number 2" :) Any tips and other implementation details are welcome.
As a clarification retrieving the currently logged in user is not an issue so you don't have to help me with it. I currently hide it behind an interface and use IoC to inject it around. Behind the scenes it uses ThreadLocals
I guess this would be the perfect use case for
Java Dynamic Proxys
Thread locals
To elucidate:
First, create your Facade Interface :
interface UserServiceFacede {
List findUsers(UserSearchParameters searchParameters, PagingParameters pagingParameters) throws AuthenticationFault, InvalidIndexFault;
void removeUser(User userToRemove) throws AutheticationFault;
void addUser(User newUser) throws AuthenticationFault;
}
Next you implement your InvocationHandler :
public class UserHandler implements InvocationHandler{
private final UserService service;
public UserHandler(UserService service) {
this.service = service;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
....
// Based on the method argument, call the appropriate function on the actual service
// object
....
}
}
You then create the Proxy object like so :
UserServiceFacade uProxy = (UserServiceFacade)Proxy.newProxyInstance(UserHandler.class.getClassLoader(),
new Class[] { UserServiceFacade.class},
new UserHandler(userService));
The first argument is the classloader, the second is the list of interfaces the Proxy must confirm to and the third is the handler object
Now the question is how do you get a handle onto your loggedinUser. This is where ThreadLocal comes in.
Create a ThreadLocal static variable that holds the loggedin user. Then set the current user into the ThreadLocal before invoking the proxy
private static final ThreadLocal loggedinUser = ...;
...
...
loggedinUser.set(currentUser);
// Create a user Proxy object as mentioned above..
uProxy.findUser(searchParams, ..);
...
Retrieve the User from the ThreadLocal inside the invoke function of the handler. Now inside the handler, you have access to both the loggedinUser (using loggedinUser.get()) as well as the user service object (You have passed in the service object into your handler's constructor)
As far as how you handle exceptions are concerned, WHat I would do is generally keep throwing a subclass of RuntimeExceptions. Then catch these at the periphery layer of your app. By periphery layer I mean, entry point into your app/library. If you were developing a webbApp this would be your Servlet.
I'm completely new to the Spring framework (and most web development in general), but I'm trying to hook up some heavy Java backend code to a new Spring and JSP project. My Controller's handleRequest() is kicking off a long running worker thread before it returns my request.jsp ModelAndView object. After that I'd like to be able to still interface with this Controller from my JSP form to be able to call isThreadDone() in the Controller whenever a button in the form is clicked. Based on three different results, I then redirect accordingly. Is this possible with my current approach? This seems to violate some of the Spring MVC approach, but I can't think of a good way to do this that I can wrap my head around. If anything is way off here, please excuse my ignorance. Thanks in advance.
Take a look at the Spring #Async annotation. If you annotate a Service-layer bean with that annotation, it then runs in its own thread, allowing your Controller thread to run without interruption after calling the Service method. Have that thread is set a value held at the Class level for the Service via synchronous methods, and your Controller code can just check those toggles at will to see if the process is done or not. Something like:
#Service
public myServiceClass {
private boolean isDone = false;
public synchronized void setIsDone(boolean isDone) {
isDone = isDone;
}
public synchronized boolean getIsDone() {
return isDone;
}
#Async
public void myServiceMethod() {
...long-running stuff...
setIsDone(true);
}
In the Controller:
#Controller
class MyController {
#RequestMapping
public kickOffHandlerMethod() {
myServiceClass.myServiceMethod();
}
}
#RequestMapping
public dependentHandlerMethod() {
if(myServiceClass.getIsDone()) {
...do something...
}
}
}
If more than one request might kick off the process, then I would save each isDone toggle in a HashMap with some kind of identifier. Then the threads would update individual toggles, one for each request.
Well, anything is possible, right? Based on what you've provided, you can just keep a reference to the thread--maybe in the HttpSession--so that when a new request comes in from clicking the button, you can query it and return an appropriate response.