How can I debug the transactions in my spring boot application ?
Is there a way to see how method calls get grouped in a transaction context or another ?
You have asked 2 broad questions here.
1. How to debug a transaction (assuming from your post title, you are looking for logging)
The simplest way to achieve is to use the bundled java.util.logging.Logger in SpringBoot.
Below code snippet should tell you how:
public class EmojiController {
private final static Logger logger = Logger
.getLogger(EmojiController.class.getName());
public ModelAndView getEmoji() {
logger.info("emoji: " + emojiId + " lookup initiated");
---do something---
}
By default, If you use the ‘Starters’, Logback will be used for logging. Appropriate Logback routing is also included to ensure that dependent libraries that use Java Util Logging, Commons Logging, Log4J or SLF4J will all work correctly.
2. Grouping the method calls related to one transaction:
This is a very wide topic and has even wider application when asked in the context of distributed application architecture like, micro-services. The point is, how do you relate various log entries with each other to group them for a wholistic view.
The solution for that lies in the concept called Distributed Tracing. You can read in detail about that in this wonderful post from Josh Long.
More detailed documentation on the discussed technologies can be found here -
Sleuth - http://cloud.spring.io/spring-cloud-sleuth/spring-cloud-sleuth.html
ZipKin - http://zipkin.io/
It should help you achieve what you want but in case you have more questions on their usage, please raise another question.
--- EDIT ---
There's a section about Logging in the Spring Reference.
It shows how to configure different logging frameworks, among them log4j
In your case the last line of the config would be:
log4j.logger.org.springframework.transaction=DEBUG
Related
This question asks for some specifics about more general topic regarding modularization of bean validation I asked before.
In question linked above, following this documentation and this post I split annotation and ConstraintValidator definition into 2 java modules, and linked them together using ServiceLoader as shown in documentation here. Works, mostly. But there is one unsolved issue, that it does not work for validation defined via XML, which I did according to documentation again. What does not work: The pairing between annotation and ConstraintValidator is not set, the service loader stuff is not used at all.
To recap: I have working setup using this ServiceLoader approach and it works when validating stuff coming through rest layer. All paired correctly.
BUT! We are getting these DTOs also through kafka. And here we have two different flows. There is some initialization of common ConstraintValidators on startup, and then:
if we first get REST message, ServiceLoader stuff is discovered only at this request time, some next initialization is done seemignly, and after that even kafka messages works, meaning pairing for custom validator is available everywhere. (Great!)
if kafka message arrives first though(typical), no service loader stuff is consulted and somehow it 'destroys' the configuration in way, that even if later rest request comes it won't work either, saying, that there is no ConstraintValidator for given annotation. The initialization is completed somehow defectively.
validation.xml is as easy as:
<validation-config
xmlns="http://xmlns.jcp.org/xml/ns/validation/configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/validation/configuration validation-configuration-2.0.xsd"
version="2.0">
<constraint-mapping>/META-INF/validation-constraints.xml</constraint-mapping>
</validation-config>
notes:
2.0 version is because of hibernate-validator 6.2.0 which comes from spring dependency management.
Why not use annotation and dump this xml stuff altogether? Not mine file, unmodifiable.
If there is some trivial newbie mistake, please advise. Maybe there is some way how to kick in service loader functionality into action in validation.xml file, I'm not aware of and cannot find anywhere.
EDITS/suggestions:
A: try to inject validator on startup to make sure it's loaded:
#Autowired
private Validator validator;
#EventListener(ApplicationReadyEvent.class)
public void logReady() {
System.out.println(validator.toString());
}
did print initialized validator, did not help though.
This is regarding CDI spec of quarkus. Would want to understand is there a configuration bean for quarkus? How does one do any sort of configuration in quarkus?
If I get it right the original question is about #Configuration classes that can contain #Bean definitions. If so then CDI producer methods and fields annotated with #javax.enterprise.inject.Produces are the corresponding alternative.
Application configuration is a completely different question though and Jay is right that the Quarkus configuration reference is the ultimate source of information ;-).
First of all reading how cdi spec of quarkus differs from spring is important.
Please refer this guide:
https://quarkus.io/guides/cdi-reference
The learnings from this guide is there is #Produces which is an alternative to #Configuration bean in Quarkus.
Let us take an example for libs that might require a configuration through code. Example: Microsoft Azure IOT Service Client.
public class IotHubConfiguration {
#ConfigProperty(name="iothub.device.connection.string")
String connectionString;
private static final Logger LOG = Logger.getLogger(IotHubConfiguration.class);
#Produces
public ServiceClient getIot() throws URISyntaxException, IOException {
LOG.info("Inside Service Client bean");
if(connectionString==null) {
LOG.info("Connection String is null");
throw new RuntimeException("IOT CONNECTION STRING IS NULL");
}
ServiceClient serviceClient = new ServiceClient(connectionString, IotHubServiceClientProtocol.AMQPS);
serviceClient.open();
LOG.info("opened Service Client Successfully");
return serviceClient;
}
For all libs vertically intergrated with quarkus application.properties can be used and then you will get a driver obj for that broker/dbs available directly through #Inject in your #applicationScoped/#Singleton bean So, Why is that?
To Simplify and Unify Configuration
To Make Sure no code is required for configuring anything i.e. database config, broker config , quarkus config etc.
This drastically reduces the amount of code written for configuring and also Junits needed to cover that code.
Let us take an example where kafka producer configuration needs to be added: in application.properties
kafka.bootstrap.servers=${KAFKA_BROKER_URL:localhost:9092}
mp.messaging.outgoing.incoming_kafka_topic_test.topic=${KAFKA_INPUT_TOPIC_FOR_IOT_HUB:input_topic1}
mp.messaging.outgoing.incoming_kafka_topic_test.connector=smallrye-kafka
mp.messaging.outgoing.incoming_kafka_topic_test.value.deserializer=org.apache.kafka.common.serialization.StringDeserializer
mp.messaging.outgoing.incoming_kafka_topic_test.key.deserializer=org.apache.kafka.common.serialization.StringDeserializer
mp.messaging.outgoing.incoming_kafka_topic_test.health-readiness-enabled=true
For full blown project reference: https://github.com/JayGhiya/QuarkusExperiments/tree/initial_version_v1/KafkaProducerQuarkus
Quarkus References for Config:
https://quarkus.io/guides/config-reference
Example for reactive sql config: https://quarkus.io/guides/reactive-sql-clients
Now let us talk about a bonus feature that quarkus provides which improves developer experience by atleast an order of magnitude that is profile driven development and testing.
Quarkus provides three profiles:
dev - Activated when in development mode (i.e. quarkus:dev)
test - Activated when running tests
prod - The default profile when not running in development or test
mode
Let us just say that in the given example you wanted to have different topics for development and different topics for production. Let us achieve that!
%dev.mp.messaging.outgoing.incoming_kafka_topic_test.topic=${KAFKA_INPUT_TOPIC_FOR_IOT_HUB:input_topic1}
%prod.mp.messaging.outgoing.incoming_kafka_topic_test.topic=${KAFKA_INPUT_TOPIC_FOR_IOT_HUB:prod_topic}
This is how simple it is. This is extremely useful in cases where your deployments run with ssl enabled brokers/dbs etc and for dev purposes you have unsecure local brokers/dbs. This is a game changer.
In all of my requests, there is a header (request id) that I want to log, in case of anything - on any log level.
Is there a way to inject this into the sl4fj logging? So that the logger always tried to log the request id, in for example logging an exception, but the request.
Or do I always need to add this as a parameter to the logging?
This is not really related to Guice.
You have in slf4j a concept of MDC (Mapped Diagnostic Context). You can put variables in an MDC. These variables are local to the thread and are added to each log generated by this thread. The typical use case of an MDC is to add in every log the user associated with an HTTP request, or a session-id (ie, your use case).
See http://logback.qos.ch/manual/mdc.html
For a short example, you put a variable in MDC like this:
MDC.put("userId", currentUser);
and you can add in an appender format the variable with:
%X{userId}
Theoretically, it could be possible to implement this feature with Guice by injecting a request-scoped logger, but it's really more costly and less integrated with the logging framework. I didn't advise you to do this kind of things!
I'm trying to debug why certain handlers in one of my controllers is not invoked by Spring's AnnotationMethodHandlerAdapter. I don't get any errors in Netbeans, just a 404 in the browser. I tried placing a breakpoint in one of my working controllers/handlers then walking up the chain to place a breakpoint in the dispatcher.
Netbeans shows me some funny method bodies:
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
{
//compiled code
throw new RuntimeException("Compiled Code");
}
which I suspect is caused by the AOP magiq. Undeterred, I tried to configure log4j to trace the calls and display any messages logged at debug level from the org.springframework.web.servlet.mvc.annotation package, but just by creating a log4j.properties file and putting in the classpath I get nothing more than the default "INFO:" level messages. Adding the context-param and listener in web.xml fails because the container can't find the log4j classes, even though they are there and even though I can add them again to the project.
So, the question is -- what do I need to do to get method traces (this could be done through AOP) and enhanced debugging (this definitely needs log4j) under Spring 3.0?
If I'm not mistaken Spring 3.X uses SLF4J for logging. Usually you would need to add SLF4J binding for your logging framework of choice - for example, for log4, slf4j-log4j12 jar should be present in classpath as well as log4j.jar and they better be proper versions - I found SLF4J to be picky about that. See more details here. Also don't forget log4j.xml config.
I am trying to put a "Contract" on a method call. My web application is in Spring 3.
Is writing customs Annotations the right way to go. If so, any pointers( I didn't find anything in spring reference docs).
Should I use tools like "Modern Jass", JML ...? Again any pointers will be useful.
Thanks
Using Spring EL and Spring security could get you most of the way. Spring security defines the #PreAuthorize annotation which is fired before method invocation and allows you to use Spring 3's new expression engine, such as:
#PreAuthorize("#customerId > 0")
public Customer getCustomer(int customerId) { .. }
or far more advanced rules like the following which ensures that the passed user does not have role ADMIN.
#PreAuthorize("#user.role != T(com.company.Role).ADMIN)")
public void saveUser(User user) { .. }
You can also provide default values for your contract with the #Value annotation
public Customer getCustomer(#Value("#{434}") int customerId) { .. }
You can even reference system properties in your value expressions.
Setting up Spring security for this purpose is not to hard as you can just create a UserDetailsService that grants some default role to all users. Alternatively you could make you own custom Spring aspect and then let this use the SpelExpressionParser to check method values.
if you don't mind writing some parts of your Java web application in Groovy (which is possible with Spring) I would suggest using GContracts.
GContracts is a Design by Contract (tm) library entirely written in Java - without any dependencies to other libraries - and has full support for class invariants, pre- and postconditions and inheritance of those assertions.
Contracts for Java which is based on Modern Jass is one way to write contracts.
http://code.google.com/p/cofoja/
As per the writing of this reply, this is pretty basic. Hopefully this will improve as we go on.
I didn't find an ideal solution to this, interestingly it is a planned feature for the Spring framework (2.0 implemented patch):
http://jira.springframework.org/browse/SPR-2698
The best thing I suggest to use JSR 303 which is for bean validation. AFAIK there are two implementations for this:
Agimatec Validations
Hibernate Validator
There's a guide here for integrating it into Spring, I haven't followed it through but it looks ok:
http://blog.jteam.nl/2009/08/04/bean-validation-integrating-jsr-303-with-spring/
I personally recommend C4J for 2 reasons:
It has Eclipse plugin so you don't need to manually configure it.
The documentation is written in a clear, structured format so you can easily use it.
Her's the link to C4J