Disable distributed tracing for development - spring-boot

We are setting up microservice framework.
We use following stack for distributed tracing.
Spring boot
Kafka
Zipkin
Following is how the configuration is done
In gradle.build (or pom.xml) following starter dependencies added
compile 'org.springframework.cloud:spring-cloud-starter-sleuth'
compile 'org.springframework.cloud:spring-cloud-sleuth-zipkin'
compile 'org.springframework.cloud:spring-cloud-starter-bus-kafka'
Add one AlwaysSampler bean
#Bean
public Sampler defaultSampler() {
return Sampler.ALWAYS_SAMPLE;
}
If we have kafka running, things work automatically.
But if kafka is not running, server does not start - this is mostly the case for development environment.
If I want to stop this, I have to comment out all the code mentioned here (as we use starter dependency with spring boot, it automatically configures as I understand).
Can we just make some changes in properties (or yaml) files so that I don't need to go and comment out all these code?
Or probably another way to disable this without doing some commenting, etc.

You can add the following setting on your properties key to disable zipkin, source.
spring.zipkin.enabled=false
Better yet, create separate development properties (like application-dev.properties) to avoid changing above setting everytime you want to run in your machine: https://stackoverflow.com/a/34846351/4504053

Related

Is there a way to generate application properties when creating a Spring Boot project?

I'm planning to run our own Spring Initializr instance. Is there a way to have a set of application properties get written (to application.yml) when a certain option is chosen, ideally in a separate section for each of a set of predefined profiles? I've looked into customising the project-generation process in Initializr and at creating a custom starter. I've come across auto-configuration for starters, but that seems to be about what configuration to default to when this has not been provided by properties, whereas I am after generating the properties. I've also come across an example of a custom Spring Initializr instance generating files, but I need it to modify application.yml without clobbering any other modifications that may have been made to it.
Spring Initializr (the library behind start.spring.io) does not have yaml support and does not allow you to write such file automatically when the project is generated.
It's easy enough for you to add that feature though. The way it works is through a model that contributors would tune + a writer that transform the model into the target output. An analogy of this would be MavenBuild and MavenBuildWriter that generates Maven's pom.xml.
Auto-configuration is indeed completely unrelated to code/configuration generation so no need to look there.

What are the consequences of checking "Disable Auto Config Detection" in the Eclipse Spring preferences?

I mean the Eclipse preference under Window|Preferences|Spring|Beans Support
"Disable Auto Config Detection".
When this option is not checked, I notice a delay when saving Java files:
Building Workspace...
Loading ...ServerApplication
or
Loading ...DaoConfig
These messages are for Spring Boot main application classes (ServerApplication) or Spring configuration classes with #ComponentScan (DaoConfig) which are located in the workspace.
This can take a few seconds, which is a bit annoying.
When I check the above preference option, I don't notice the delay for loading these classes (at least for the Spring Boot main classes).
What are the consequences of disabling Auto Config Detection, e.g. what does this option really do, what functionality do I loose? Any pointers to documentation?
Can I speed up the save process without having to disable Auto Config Detection?
In STS3, the IDE creates an internal model of your Spring application, so that it can display a nice overview of your Spring elements in the Spring Explorer view, provide content-assist in Spring XML config files and more. In order to build up this internal Spring beans model, it needs to know where to start from when building that model. You can define those entry points manually in the properties for each project: Spring -> Beans Support. That preference allows you to define Spring XML config files and/or Spring-annotated configuration classes to be used by the IDE internally to build up that model.
In addition to that there is a mechanism to detect those files (Spring XML config files and Spring Boot application configuration annotations) automatically, so that you don't need to configure them manually. But the result is the same. Those files/classes end up being configured to be used by the IDE to built this internal model.
I guess that the delay that you see comes from building this internal beans model - this is at least what the messages indicate that you mentioned.
So far for the background. You can disable that auto-config mechanism and you don't need to configure those files/classes manually. This will result in the Spring Explorer, for example, not showing anything meaningful for those projects.
As an alternative and in case you are working mostly with Spring Boot projects, I would strongly recommend to switch to the all-new Spring Tools 4 (also available as a ready-to-use Eclipse distribution). It provides a slightly different set of features and is implemented in a different way, so that it doesn't need the expensive internal bean model creation. You should give it a try. And if you are missing something that you love in STS3 that is not yet part of Spring Tools 4, let us know.

Including profiles via a Spring Boot starter

I'm having issues with a custom Spring Boot starter. How can a starter cause a profile to be included and pull related configuration from a config server?
Perhaps my use case is unique, because I haven't found any helpful information online. I'm working in an enterprise environment and this starter is for use by my team, so we're able to control some things (like profile names) that perhaps wouldn't make sense in the open source world.
Here is the scenario: We have a Spring Cloud Config Server running to provide configuration. Across our Spring Boot projects, we have standardized on certain profile names such as "prod" and "nonprod" to control configuration in our different environments. I am trying to create a starter to provide reusable functionality. For example purposes, let's say I'm creating a starter that provides an interface to an appliance that performs cryptographic work for us. This starter will need the IP address of the appliance and various other configuration which differs between production and non-production.
Within the config repo, I will have files such as application.yml, application-nonprod.yml, application-nonprodEncryption.yml, etc.
My goal is to have the custom encryption starter automatically include the nonprodEncryption profile when that starter is included in an application. By doing this, apps which don't need encryption do not load the encryption related properties.
Here are my experimental findings so far:
Within an application's bootstrap.yml, I can put a block such as
spring.profiles: nonprod
spring:
profiles:
include:
- nonprodEncryption
and that produces the desired result (i.e. the application-nonprodEncryption.yml file is loaded from the config server and used), but this is an undesirable solution as every app that uses my custom starter would need to include this boilerplate configuration.
When I move the above configuration to the starter's bootstrap.yml, it seems to have no effect.
When I move the above configuration to the starter's application.yml, it seems to be applied (i.e. it shows up in the The following profiles are active: list), but it is too late in the lifecycle to cause the appropriate configuration to be pulled from the config server.
Other things I've considered:
Why not just put all of the configuration into the main profile config file (e.g. application-nonprod.yml)? From a separation of concerns and maintenance standpoint, I'd like to keep configuration for individual starters isolated from each other. Also, some configuration data is more sensitive than other config data, so I don't like the idea of exposing all of the configuration to all apps, since many apps won't need some of the more sensitive configuration. Yes, they could get to it, but why load it into their memory if they don't need it?
Why not just specify the extra profiles when we launch the app? These apps will be running on a cloud platform. The platform will specify either "prod" or "nonprod" as the profile based on which tier the app is running in. I want to manage that at the platform level rather than the app level, so I want the list of profiles provided at app launch to be uniform across all apps (add adding, for example, nonprodEncryption to the list just gets me into the same situation as above - all apps would have all of the configuration, so I might as well just put it all in a single file).
We are currently using Spring Boot 1.5.10.
Any thoughts on how to achieve what I'm trying to do?
I finally found a solution (in case anyone else finds themselves in the same spot).
Step 1: Add a configuration class like this to your starter:
package com.company.bootstrap;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Profile;
#Configuration
#Profile("nonprod")
public class BootstrapNonprod {
public BootstrapNonprod(ConfigurableApplicationContext ctx) {
ctx.getEnvironment().addActiveProfile("nonprodEncryption");
}
}
This will conditionally add a profile. In this example, whenever the "nonprod" profile is active, this class will add the "nonprodEncryption" profile.
Step 2: In your starter's spring.factories file, add a line such as this:
org.springframework.cloud.bootstrap.BootstrapConfiguration=com.company.bootstrap.BootstrapNonprod
It seems like it is just that simple.

In a spring-boot application, is it possible to change the dependency injection by external configuration?

I am building an application to send email but I want to turn off the actual send and just have it output to a log file in non-prod environments. The class that actually sends mail is a Spring injected dependency, so my thought was just to build a no-op implementation to swap out with the actual implementation.
Second requirement, I don't want to create separate builds for different environments. I want to create one and promote it through dev -> test -> prod.
This seems like a common use case for dependency injection but I don't see how to externally configure it. If I want to do it this way do I need to abandon annotation based injection and use xml instead?
You can add #Profile("PRODUCTION") on your production #Bean and #Profile("!PRODUCTION") on your non-production #Bean. Then you can specify the active profile(s) at runtime:
java -jar bootApp.jar --spring.profiles.active=PRODUCTION, ...

Runtime dependency (e.g. connection pooling) and classpath?

I have a Maven 3 project that uses Hibernate 3. In the Hibernate properties file, there is an entry for hibernate.connection.provider_class with the class corresponding to the C3P0 connection provider (org.hibernate.connection.C3P0ConnectionProvider). Obviously, this class is only used at runtime, so I don't need to add the corresponding dependency in my POM with the compile scope. Now, I want to give the possibility to use any connection pooling framework desired, so I also don't add a runtime dependency to the POM.
What is the best practice?
I thought about adding an entry to the classpath corresponding to the runtime dependency (in this case, hibernate-c3p0) when the application is run (for example, using the command line). But, I don't know if it's possible.
This is almost (maybe exactly) the same problem as with SLF4J. I don't know if Hibernate also uses the facade pattern for connection pooling.
Thanks
Since your code doesn't depend on the connection pooling (neither the main code nor the tests need it), there is no point to mention the dependency anywhere.
If anyone should mention it, then that would be Hibernate because Hibernate offers this feature in its config.
But you can add it to your POM with optional: true to indicate:
I support this feature
If you use it, then I recommend this framework and this version
That will make life slightly more simple for consumers of your project.
But overall, you should not mention features provided/needed by other projects unless they have some impact on your code (like when you offer a more simple way to configure connection pooling for Hibernate).
[EDIT] Your main concern is probably how to configure the project for QA. The technical term for this new movement is "DevOps" - instead of producing a dump WAR which the customer (QA) has to configure painstakingly, configuration is part of the development process just like everything else. What you pass on is a completely configured, ready-to-run setup.
To implement this, create another Maven module called "project-qa" which depends on your project and everything else you need to turn the dead code into a running application (so it will depend on DBCP plus it will contain all the necessary config files).
Maven supports overlayed WARs which will allow you to implement this painlessly.
You can mark your dependency as optional. In this case it will not be packaged into archives. In this case you have to ensure that your container provides required library.
You could use a different profile for each connection provider. In each profile you put the runtime dependency that correspond to the connection provider you want to use and change the hibernate.connection.provider_class property accordingly.
For more details about how to configure dependencies in profiles, see Different dependencies for different build profiles in maven.
To see how to change the value of the hibernate.connection.provider_class property see How can I change a .properties file in maven depending on my profile?

Resources