I am trying to implement a CXF Server flow as below. I want to synchronously invoke the VM from the Java component (after CXF component). However to synchronously invoke the VM, I need MuleContext (for eg: muleContext.send("vm://some_name", MuleMessage)). I am currently stuck, unable to find a way to access the Mule Flow's MuleContext inside Java component within the Flow.
Any help is highly appreciated..
Mule Flow Structure
Thanks,
Aneesh.
Check out the MuleSoft documentation https://docs.mulesoft.com/mule-user-guide/v/3.8/java-component-reference on writing a Java Component.
If your Java class implements the org.mule.api.lifecycle.Callable interface then you will be able to override the following method,
public Object onCall(MuleEventContext eventContext)
Inside this method you synchronously call the VM like this,
eventContext.sendEvent(message, endpoint)
Related
The AWS SDK can locate API call interceptors via classpath scanning (looking for software/amazon/awssdk/global/handlers/execution.interceptors and instantiating classes specified there).
I'm writing a Java Agent with the intention of causing my interceptors to be locatable by the AWS SDK.
My interceptor is bundled with the Java Agent.
My interceptor implements AWS's ExecutionInterceptor.
The AWS SDK is not bundled with my agent, because I'd like the end-user to provide their own AWS SDK version.
For regular standalone applications, this is a no-brainer, as the Java Agent is automatically added to the runtime classpath of the application. The AWS SDK finds my interceptors with no problem.
However, this approach completely breaks with Spring Boot applications where the AWS SDK is bundled as a dependency under BOOT-INF/lib. The reason boils down to Spring Boot's classloading hierarchy. My interceptor class can be found, but its loading fails due to inability to find AWS's ExecutionInterceptor, as it is loaded in a "lower" classloader in the hierarchy.
So I figured that my approach should be to somehow modify Spring Boot's classloader search. However, I'm facing these issues:
At the time of the agent being called, Spring Boot's "lower" classloader isn't created yet.
I am not entirely sure what it is that I need to instrument.
I've read of Byte Buddy being able to help in such "interesting" circumstances but haven't found a way to make this work yet. Any ideas?
(EDIT: I'm looking for a solution that doesn't require code/packaging changes, hence the Java Agent approach)
(EDIT: Things I've tried)
Following Rafael's answer: The method in the SDK that resolves all interceptors is in the class SdkDefaultClientBuilder, and is called resolveExecutionInterceptors.
The following, then, works for standalone JARs which are not SpringBoot applications:
public static void installAgent(Instrumentation inst) {
new AgentBuilder.Default()
.with(RedefinitionStrategy.DISABLED)
.type(ElementMatchers.nameEndsWith("SdkDefaultClientBuilder"))
.transform(
new Transformer() {
#Override
public Builder<?> transform(Builder<?> builder, TypeDescription typeDescription,
ClassLoader classLoader, JavaModule module) {
return builder.visit(Advice.to(MyAdvice.class).on(ElementMatchers.named("resolveExecutionInterceptors")));
}
}
).installOn(inst);
}
For SpringBoot applications, however, it looks like the advice isn't applied at all. I am guessing that this is because the SdkDefaultClientBuilder type isn't even available at the time when the agent starts. It is available during SpringBoot's runtime, in a different classloader.
Byte Buddy allows you to inject code in any method of any class, so the first and only major thing you would need to find out would be where your interceptor is instantiated. This can typically be done by setting a breakpoint in the constructor of the interceptor in the working scenario and investigating the methods in the stack. Find out where the classes are discovered, for example the method where software/amazon/awssdk/global/handlers/execution.interceptors is read.
Once you have identified this method, you would need to find a way to manually extract the interceptors defined by your agent and to manually add them. For example, if the file-extracted interceptors are added to an argument of type List<Interceptor>, you could use Byte Buddy to modify this method to also add those of your agent.
Normally, you use Byte Buddy's AgentBuilder in conjunction with Advice to do so. Advice let's you inline code into another method as for example, assuming you find a method with an argument of type List<Interceptor>:
class MyAdvice {
#Advice.OnMethodEnter
static void enter(#Advice.Argument(0) List<Interceptor> interceptors) {
interceptors.addAll(MyAgent.loadMyInterceptors());
}
}
You can now inline this code into the method in question by:
class MyAgent {
public static void premain(String arg, Instrumentation inst) {
new AgentBuilder.Default().type(...).transform((builder, ...) -> builder
.visit(Advice.to(MyAdvice.class).on(...))).install(inst);
}
}
You might need to use AgentBuilder.Transformer.ForAdvice if the classes in question are not available on the agent's class loader where Byte Buddy resolves the advice using both the target and the agent class loader.
I am using the Service Grid based on Apache Ignite .Net and I am seeking to implement the distributed tracing for requests spanning multiple Ignite services.
To implement that, I need to pass a request id (also known as correlation id) through the entire call chain. So I wonder if there is a way to transparently pass some context information from an Ignite service caller to the target Ignite service without wrapping the method arguments in some form of envelope? That would enable me to keep the method arguments clean.
I see that there is the void Execute(IServiceContext context) method that gives access to some context information on the receiving side. Is there a way to manipulate the context on the client side?
Thank you!
void Execute(IServiceContext context) method is invoked automatically whenever an instance of the service is deployed on a grid node, and ServiceContext instance is created inside the grid on service deployment, so it's not intended to be manipulated somehow from the client side.
In described case some kind of correlation id can be added to the service's methods signatures.
I'm wondering whether sleuth has reactive WebClient instrumentation supported.
I did't find it from the document:
Instruments common ingress and egress points from Spring applications (servlet filter, async endpoints, rest template, scheduled actions, message channels, Zuul filters, and Feign client).
My case:
I may use WebClient in either a WebFilter or my rest resource to produce Mono.
And I want:
A sub span auto created as child of root span
trace info propagated via headers
If the instrumentation is not supported at the moment, Am I supposed to manually get the span from context and do it by myself like this:
OpenTracing instrumentation on reactive WebClient
Thanks
Leon
Even though this is an old question this would help others...
WebClient instrumentation will only work if new instance is created via Spring as a Bean. Check Spring Cloud Sleuth reference guide.
You have to register WebClient as a bean so that the tracing instrumentation gets applied. If you create a WebClient instance with a new keyword, the instrumentation does NOT work.
If you go to Sleuth's documentation for the Finchley release train, and you do find and you search for WebClient you'll find it - https://cloud.spring.io/spring-cloud-static/Finchley.RC2/single/spring-cloud.html#__literal_webclient_literal . In other words we do support it out of the box.
UPDATE:
New link - https://docs.spring.io/spring-cloud-sleuth/docs/current/reference/html/integrations.html#sleuth-http-client-webclient-integration
let me paste the contents
3.2.2. WebClient
This feature is available for all tracer implementations.
We inject a ExchangeFilterFunction implementation that creates a span
and, through on-success and on-error callbacks, takes care of closing
client-side spans.
To block this feature, set spring.sleuth.web.client.enabled to false.
You have to register WebClient as a bean so that the tracing
instrumentation gets applied. If you create a WebClient instance with
a new keyword, the instrumentation does NOT work.
I am registering my component like this:
public static void Register(IWindsorContainer container)
{
container.Register(Classes.FromAssembly(Assembly.GetAssembly(typeof(GenericBaseRepository)))
.InSameNamespaceAs<GenericBaseRepository>()
.WithService.DefaultInterfaces()
.LifestyleTransient());
}
I am then resolving it in a piece of code that has no HttpContext:
var baseRepository = ContainerManager.Container.Resolve<IBaseRepository>();
(IBaseRepository being an interface implemented by GenericBaseRepository). This fails with the following message:
"HttpContext.Current is null. PerWebRequestLifestyle can only be used in ASP.Net"
Which confuses me, because the lifestyle I choose is Transient, not PerWebRequest.
Of course, HttpContext doesn't exist during a scheduled task - but I don't really need it, I just want an instance of my Repository which will not interact with any web request.
So, why does Castle Windsor insist in requiring an HttpContext when resolving my component?
Have a look at the full exception message. Your root component may be transient but the exception indicates one of its dependencies uses per web request lifestyle.
Have a look at Windsor's diagnostics debugger view, that may help you pinpoint it.
I'm new to webservices and I have some questions but I hope to get a more clear picture by asking.
I've created a simple webservice with Apache CXF and it works.
I what at startup to build some objects, like database connection or... for example a new thread.
I want the following scenario:
-all the requests should access only the published methods of the webservice.
-all the methods must access varialbes of the running background startup threads.
So the threads will run in background and the published methods will access their result stored in ...maybe a static varialbes.
At the moment I'm using TomcatServer7
The class that it's methods are published is looking like this:
public class OperatorClass {
public int add(int a, int b){
return a+b;
}
public int OneArgument(int a){
return a+45;
}
}
How is possible to implement this and where to write the startup thread clases? maybe a sample code or a link to see how it's done would be very useful.
Tks
If you are using Spring with CXF you can create a bean and implement InitializingBean interface, then in afterPropertiesSet() method you can start you threads depending on your needs. The other alternative with Spring is to use: #PostConstruct annotation on the method which you want to be called after dependency injection.
If you are not using Spring then you can set up ServletContextListener to do the job. See my answer here for more information how to set up context listener.
And now there are many ways of getting the data from the threads you've started on start up. You just need to come up with a more specific question (if you can't get it working) and we will be glad to help.