Customizing Apache Camels ExchangeFormatter using Spring-Boot - spring-boot

by default i assume that spring-boot/camel is using org.apache.camel.support.processor.DefaultExchangeFormatter.
I wonder how I can set the flag 'showHeaders' inside a spring-boot app.
Because I hope to see the headers in the "org.apache.camel.tracing" log as well.
Wish all a wonderful day

DefaultTracer is used in Camel to trace routes by default.
It is created with showHeaders(false) formatter option set.
Therefore you could implement another Tracer (consider extending from DefaultTracer) to enable putting headers into traced messages.

i need this mostly in my tests. so i have built this into my basic test class
#BeforeEach
public void before() {
if( camelContext.getTracer().getExchangeFormatter() instanceof DefaultExchangeFormatter ) {
DefaultExchangeFormatter def = (DefaultExchangeFormatter)camelContext.getTracer().getExchangeFormatter();
def.setShowHeaders(true);
}
}

Related

How to test ApplicationStartedEvent in Spring Boot?

I need to write an application startup event listener, here I have an #EventListener:
#EventListener
public void onApplicationEvent(ApplicationStartedEvent startedEvent)
How do I go with this? What I have done until now is, wrote many other unit tests but don't understand if I should (somehow) create an object for the ApplicationStartedEvent which doesn't sound right.
Other questions on SO like this one provide information about creating tests for custom events but this isn't a custom event and I don't want to create this object manually.
I solved it differently as I wanted to unit-test this, but seems like we can only write an Integration Test for this.
Used the following to create sample data:
private static final EasyRandomParameters EASY_RANDOM_PARAMETERS = new EasyRandomParameters()
.seed(123L)
.objectPoolSize(100)
.randomizationDepth(3)
.charset(StandardCharsets.UTF_8)
.timeRange(LocalTime.of(9, 0), LocalTime.of(17, 0))
.stringLengthRange(5, 50)
.collectionSizeRange(1, 10)
.scanClasspathForConcreteTypes(true)
.overrideDefaultInitialization(false)
.ignoreRandomizationErrors(true);
public static <T> T create(Class<T> ofType) {
EasyRandom easyRandom = new EasyRandom(EASY_RANDOM_PARAMETERS);
return easyRandom.nextObject(ofType);
}
And used it like:
ApplicationStartedEvent applicationStartedEvent = create(ApplicationStartedEvent.class);
Then called the required method. Not exactly the event listener of course but did the job.

How do I define the Abp language to use during unit test execution?

I am creating unit tests for my service layer. I used the existing UserAppService_Tests test that comes with the downloaded template as a guide.
However I am seeing this exception thrown.
Abp.AbpException : No language defined!
My Test inherits from GpTestBase which in turn inherits from AbpIntegratedTestBase<GpTestModule>
GpTestModule has :
Configuration.Modules.Zero().LanguageManagement.EnableDbLocalization();
So I thought that it should be ok.
Any clues?
public override void PreInitialize()
{
Configuration.UnitOfWork.Timeout = TimeSpan.FromMinutes(30);
Configuration.UnitOfWork.IsTransactional = false;
// Disable static mapper usage since it breaks unit tests (see https://github.com/aspnetboilerplate/aspnetboilerplate/issues/2052)
Configuration.Modules.AbpAutoMapper().UseStaticMapper = false;
Configuration.BackgroundJobs.IsJobExecutionEnabled = false;
// Use database for language management
Configuration.Modules.Zero().LanguageManagement.EnableDbLocalization();
RegisterFakeService<AbpZeroDbMigrator<GpDbContext>>();
Configuration.ReplaceService<IEmailSender, NullEmailSender>(DependencyLifeStyle.Transient);
}
You should not be defining the language to use explicitly.
To have a localization context, you should login as a user.
This can happen if you don't have any languages defined in the AbpLanguages table. Example here.
In my case, it was caused by public const bool MultiTenancyEnabled = true;. Changing MultiTenancyEnabled to false, solved the problem.

How to register a Renderer with CRaSH

After reading about the remote shell in the Spring Boot documentation I started playing around with it. I implemented a new Command that produces a Stream of one of my database entities called company.
This works fine. So I want to output my stream of companies in the console. This is done by calling toString() by default. While this seams reasonable there is also a way to get nicer results by using a Renderer.
Implementing one should be straight forward as I can delegate most of the work to one of the already existing ones. I use MapRenderer.
class CompanyRenderer extends Renderer<Company> {
private final mapRenderer = new MapRenderer()
#Override Class<Company> getType() { Company }
#Override LineRenderer renderer(Iterator<Company> stream) {
def list = []
stream.forEachRemaining({
list.add([id: it.id, name: it.name])
})
return mapRenderer.renderer(list.iterator())
}
}
As you can see I just take some fields from my entity put them into a Mapand then delegate to a instance of MapRenderer to do the real work.
TL;DR
Only problem is: How do I register my Renderer with CRaSH?
Links
Spring Boot documentation http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-remote-shell.html
CRaSH documentation (not helping) http://www.crashub.org/1.3/reference.html#_renderers

use camel case serialization only for specific actions

I've used WebAPI for a while, and generally set it to use camel case json serialization, which is now rather common and well documented everywhere.
Recently however, working on a much larger project, I came across a more specific requirement: we need to use camel case json serialization, but because of backward compatibility issues with our client scripts, I only want it to happen for specific actions, to avoid breaking other parts of the (extremely large) website.
I figure one option is to have a custom content type, but that then requires client code to specify it.
Is there any other option?
Thanks!
Try this:
public class CamelCasingFilterAttribute : ActionFilterAttribute
{
private JsonMediaTypeFormatter _camelCasingFormatter = new JsonMediaTypeFormatter();
public CamelCasingFilterAttribute()
{
_camelCasingFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
}
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
ObjectContent content = actionExecutedContext.Response.Content as ObjectContent;
if (content != null)
{
if (content.Formatter is JsonMediaTypeFormatter)
{
actionExecutedContext.Response.Content = new ObjectContent(content.ObjectType, content.Value, _camelCasingFormatter);
}
}
}
}
Apply this [CamelCasingFilter] attribute to any action you want to camel-case. It will take any JSON response you were about to send back and convert it to use camel casing for the property names instead.

Add Aspects to ASP.NET MVC controller using AspectMap

We're looking at using an AOP framework for handling things like logging, tracing, and exception handling. I've built a prototype using PostSharp and now I'm trying to build the same functionality using AspectMap.
In a nutshell, I have an ASP.NET MVC 3 application and I want an aspect that I can easily attach to my controller methods that shows the entry, exit, execution time, and argument values. My PoC is the basic MVC 3 Internet Application template (File > New > Project > Web > ASP.NET MVC 3 Web Application > Internet). What I've done so far...
Created an AspectsRegistry
public class PoCRegistry : AspectsRegistry
{
public PoCRegistry()
{
ForAspect<ProfileAttribute>().HandleWith<ProfileHandler>();
}
}
Created a StructureMapControllerFactory
public class StuctureMapControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance( RequestContext requestContext, Type controllerType )
{
if( controllerType == null ) return null;
try
{
return ObjectFactory.GetInstance( controllerType ) as Controller;
}
catch( StructureMapException )
{
Debug.WriteLine( ObjectFactory.WhatDoIHave() );
throw;
}
}
}
Registered everything in Application_Start
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters( GlobalFilters.Filters );
RegisterRoutes( RouteTable.Routes );
ObjectFactory.Initialize( ie => ie.AddRegistry( new PoCRegistry() ) );
ControllerBuilder.Current.SetControllerFactory( new StuctureMapControllerFactory() );
}
At this point the application works, and I can see it's using my StructureMapControllerFactory to build the controller (debugger steps into that code). The problem is that I can't figure out where or how to "enrich" the controller that is generated. In the tutorial it says I need to use something like the following:
For<ICaseController>()
.Use<CaseController>()
.EnrichWith( AddAspectsTo<CaseController> );
But in the tutorial that goes in the AspectRegistry, which doesn't seem like the right place in this situation because the registry isn't responsible for resolving the controller request, the controller factory is. Unfortunately the GetInstance() method in the controller factory returns an object and the EnrichWith() method needs a SmartInstance.
At this point I'm stuck. Any hints, pointers, or assistance would be appreciated.
This is a use case I hadn't thought about to be honest. I'll setup a test project today and see what I can come up with. Bear with me!
Update
I've been playing around with the backend code (you can get a complete copy of the code from http://aspectmap.codeplex.com) and the relevant part is this:
public T AddAspectsTo<T>(T concreteObject)
{
ProxyGenerator dynamicProxy = new ProxyGenerator();
return (T)dynamicProxy.CreateInterfaceProxyWithTargetInterface(typeof(T), concreteObject,
new[] { (IInterceptor)new AspectInterceptor(attributeMap) });
}
This is using the castle dynamic proxy stuff. Unfortunately the CreateInterfaceProxy... methods require that an interface is passed in (rather than a base class like I'd hoped). Now I've found this question:
C# Dynamic Proxy 2 generate proxy from class with code in constructor ? How to?
That seems to show that it could be possible to use CreateClassProxy. I've not had chance to try this out yet and I'm going away for a week away from the computer. If you want to try and wire it up though you're welcome to get the source from codeplex and give it a try though. If not I'll put something together when I return.
Action filters can be used to provide such AOP functionality.
http://www.asp.net/mvc/tutorials/older-versions/controllers-and-routing/understanding-action-filters-cs
http://msdn.microsoft.com/en-us/library/dd410056%28v=vs.90%29.aspx

Resources