For a Spring application I want to add a custom field to the log.
Currently I use the default format but I want to add a custom field (category field) which should be present in all the logs:
W:Action D:2022-01-10 23:21:03.285 L:INFO C:c.h.l.LoggingDemoApplication F:StartupInfoLogger.java(61) Fn:logStarted T:main R: - Hello World
What are the best solution to add a custom field to the logback log?
What I studied until now are the following possible solutions:
Use marker. The disadvantage with this is that it's not scalable: if in future you need another custom field can't add another marker. Further based on some other posts the marker is best suited to mark special logs that need to be handle differently.
Use MDC.
Also using this it seems not the best solution because:
It keeps the context so if there are multiple log statements in the same function, before each logger.info() there should be MDC.put("category", "action")
The code becomes to verbose.
Create a custom convertor (link). Get the arguments from the ILoggingEvent, get argument of 0. If this is the same type as category enum, then use it. The call for this is like logger.info("Message here: {} {} {}", CatEnum.Action.getValue(), msg1, msg2, msg3).
Create some static method in which the final format is generated.
Pattern is similar to: <pattern>%m%n</pattern>
To log, something like this should be used: logger.info(customFormatter.fmtLog(CatEnum.Action.getValue(), msg)). The returned value of fmtLog should be all the info from default logging + the category field.
Are there any built in solutions to add a custom field?
Related
I have been trying go through code of Broadleaf Commerce. There were multiple Custom Annotations used however I was not able to locate there Processor. Can anyone help me here. To take example #AdminPresentation it a custom annotation in package org.broadleafcommerce.common.presentation;
However how this is processed throughout the app, I was not able to locate. What I have understood till now we can use Reflection or AOP for its processing. But There was nothing for this.
Please help.
Source code - https://github.com/BroadleafCommerce/BroadleafCommerce
For a short answer, org.broadleafcommerce.openadmin.server.dao.provider.metadata.BasicFieldMetadataProvider#addMetadata is one place that processes those annotations.
On a broader level, the controllers in the openadmin will use the AdminEntityService to get ClassMetaData (all data about how a class should be displayed to an admin user). The #AdminPresentation annotation is one source of this data. The method AdminEntityServiceImpl#getClassMetadata is the main gateway for getting the ClassMetaData.
#getClassMetadata calls #inspect and eventually gets to PersistenceManager#inspect. This method uses the DynamicEntityDao to eventually get to Metadata#getFieldMetadataForTargetClass. That method gets each field of a class via reflection, and then each of those Fields is processed through the available FieldMetadataProviders. The FieldMetadataProviders turn a java.lang.reflect.Field into org.broadleafcommerce.openadmin.dto.FieldMetadata.
Any provided FieldMetadataProvider can contribute field metadata. This metadata is used in the FormBuilderService to construct the admin page.
Class References:
AdminEntityService - org.broadleafcommerce.openadmin.server.service.AdminEntityServiceImpl
PersistenceManager - org.broadleafcommerce.openadmin.server.service.persistence.PersistenceManagerImpl#inspect
DynamicEntityDao - org.broadleafcommerce.openadmin.server.dao.DynamicEntityDaoImpl#getPropertiesForEntityClass
Metadata - org.broadleafcommerce.openadmin.server.dao.Metadata#getFieldMetadataForTargetClass
FieldMetadataProvider - org.broadleafcommerce.openadmin.server.dao.provider.metadata.FieldMetadataProvider, org.broadleafcommerce.openadmin.server.dao.DynamicEntityDaoImpl#fieldMetadataProviders
FormBuilderService - org.broadleafcommerce.openadmin.web.service.FormBuilderServiceImpl
Have a look to :
https://www.baeldung.com/java-custom-annotation
You will get explanations about : "default" in the Custom Annotations.
Florent COUDERT.
The values I want to provide dynamically is TestCase Name and Package name. How can I do this. If I am providing values through variable then it is giving the following error "The value for annotation attribute CitrusXmlTest.name must be a constant". Now I am giving like this
#CitrusXmlTest(name="Test",packageName="file:D://xitrus//myFirstTest.xml")
I want above statement to be
#CitrusXmlTest(name=variable name,packageName=variable name)
or in some other way to insert values dynamically please help me...
pom image 1,image 2,image 3
What you are trying to do is against Java annotation specification and is not possible due to these language limitations. Not sure what you are trying to achieve here.
In case you need to load test cases in a dynamic way you can use packageScan option in #CitrusXmlTest annotation:
#CitrusXmlTest(packageScan = "com.something.foo")
public void citrusPackageScanIT() {}
This will load and execute all XML test case definitions in package com.something.foo. The XML test definitions are free to use different test names then.
If you want to pass some dynamic data to your test case you should use a TestNG data provider (example given here: https://github.com/christophd/citrus-samples/tree/master/sample-dataprovider).
I need to add a custom field to log entries, like this:
[KEYWORD] [Date/Time] [LEVEL] [Message]
The KEYWORD can be present or not in the log entry depending on a boolean value I pass to the log methods:
logger.info("message here", true) // Keyword is present
logger.error("message here", false) // keyword is not in log entry
Is this possible using the machinery provided by log4j, without changing its code?
p.s. I know I can add the custom field in the message part. I am wondering how hard it is if I insist on placing the field at the beginning of the log entry.
I think you can write your implementation of logger by extending log4j
The situation is the following:
I have a JSP page with a form.
This form contains various <select> tags with options loaded from DB.
I want to use validation with an XML file.
The problem is the following: if I use an XML file and there are some errors in the form fields, the struts framework doesn't pass through the class method I laid out, but it will directly return the input result. So what's the point? That in this way I can't load the options for the various <select> tags I mentioned above.
So I thought to do something like this:
<result name="input" type="chain">
<param name="actionName">Class_method</param>
</result>
but with this trick I lose all the error messages, i.e. hasFieldErrors() returns always false.
How can I solve that?
Many questions, all good though.
Conversion and validation errors forces the Workflow interceptor to trigger the INPUT result, and the workflow will execute the INPUT result instead of reaching the action method (execute() or whatever).
If you need to populate some static data, like selectboxes sources, that must be available also in case of INPUT result, you should put that loading in a prepare() method, and make your action implement the Preparable interface. This method is run by an Interceptor before the INPUT result is returned, as described in the official docs.
Avoid using the chain result. It is officially discouraged since many years.
If you want to prevent double submits (by pressing F5 after a page has been submitted and the result rendered), you can use the PRG pattern with the redirectAction result. This way, however, you'd encounter the same problem of the chain result: the messages (and the parameters) will be lost.
To preserve the error messages, action errors and field errors across the redirections, you can use a predefined interceptor called Message Store Interceptor, that you must include in your stack because the defaultStack doesn't include it. I've described how it works in this answer.
If you decide to use the Message Store along with PRG there are more considerations, too long to be written here, but that could be explained in the future, about preventing infinite recursion due to Field Error -> INPUT -> PRG -> Retrieve Field Error -> INPUT -> etc... that will be blocked by the browser near the 10th recursion... but that's another story.
One option:
public class Foo extends ActionSupport {
public string myAction() { return SUCCESS; }
public void validateMyAction() { // executed after XML validation
// other complex validation here if needed
if (hasErrors()) {
// repopulate form data from DB here
}
}
}
hasErrors() method comes from the ValidationAware interface which ActionSupport implements.
Another option is to do a redirect on input result and use the message store interceptor to keep action messages
I'm using Play Framework and setting a cache value as such:
String sessionId = Scope.Session.current().getId();
Cache.set(sessionId + "_user", "Doser");
and I want to ouput the value in my main.html without adding the value to every single controller in my application.
How do I achieve this in Play?
The other option you have for this, is to create an action in your controller that uses the #Before annotation, and then add the value using renderArgs().
I answered a previous question which I think is very similar to your requirements.
Does Play Framework support "snippets"?
You should also be aware that all session variables are available within your template, by default. You can see all the implicit objects that are available in the template in the Template Documentation here -- http://www.playframework.org/documentation/1.2.2/templates#implicits.
I need to stop answering my own questions.
I've created a tag as described in the link below, and it works perfectly:
http://www.playframework.org/documentation/1.2.2/templates#tags