Specify client.id per KafkaTemplate - spring-kafka

I know that it is possible to define client.id for each #KafkaListener.
Is it possible to define client.id for each KafkaTemplate?
It is easier to read the kafka-logs, if I can define the client.id per KafkaTemplate instead of relying on Spring assigning a suffix to each producer.

Spring Kafka doesn't assign any client.id into the Producer it creates:
protected Producer<K, V> createKafkaProducer() {
return new KafkaProducer<K, V>(this.configs, this.keySerializer, this.valueSerializer);
}
Unless you provide one via ProducerConfig.CLIENT_ID_CONFIG into those mentioned configs.
So, for each your KafkaTemplate you need to declare a separate DefaultKafkaProducerFactory and share common properties via Map<String, Object> configs, but use unique ProducerConfig.CLIENT_ID_CONFIG for each instance.
Alternatively you can implement your own ProducerFactory to populate a unique ProducerConfig.CLIENT_ID_CONFIG each time its createProducer() is called.

Related

Kotlin: Json: conflicting annotation schemes for name transcription

I read data from Firebase database into a Kotlin/Android program. The key names in Firebase are different from those of the corresponding Kotlin variables. I test this code with flat JSON files (for good reasons) where I retain the same key names used in Firebase, so I need to transcribe them too.
Firebase wants to annotate variables with #PropertyName; but Gson, which I use to read flat files, wants #SerializedName (which Firebase doesn't understand, unfortunately.)
Through trial and error I found that this happens to work:
#SerializedName("seq")
var id: Int? = null
#PropertyName("seq")
get
#PropertyName("seq")
set
Both Firebase and Gson do their thing and my class gets its data. Am I hanging by a thin thread here? Is there a better way to do this?
Thank you!,
You can probably solve this by using Kotlin's #JvmField to suppress generation of getters and setters. This should allow you to place the #PropertyName annotation directly on the property. You can then implement a Gson FieldNamingStrategy which checks if a #PropertyName annotation is present on the field and in that case uses its value; otherwise it could return the field name. The FieldNamingStrategy has to be set on a GsonBuilder which you then use to create the Gson instance.

How can intercept ConcurrentMessageListenerContainer when I'm using ConcurrentKafkaListenerContainerFactory

I'm using spring-kafka-2.2.7.RELEASE and trying to create a consumer using #KafkaListener at method level in conjunction with ConcurrentKafkaListenerContainerFactory. As per my understanding, this would create a ConcurrentMessageListenerContainer.
Is there an interceptor to intercept this container creation so that I can inject my custom logic to build groupId?
If I have two different methods using #KafkaListener to consumer two different topics, would it create two ConcurrentMessageListenerContainers?
If you have #KafkaListener(id = "foo", ..., autoStartup = "false") you can auto wire the KafkaListenerEndpointRegistry, and then...
registry.getListenerContainer("foo").getContainerProperties().setGroupId(...);
registry.getListenerContainer("foo").start();
However, you can simply use
#KafkaListener(... groupId "${some.property}")
or
#KafkaListener(... groupId "#{someSpelExpression}")
if all you want to do is set the group id.
Yes, a separate container is created for each annotated method.

How Can I make Spring-MVC #PropertySources load first, before any other configuration

I have a spring-mvc application that is using java configuration, not xml. There are #Configuration annotations sprinkled through several files. In particular, there is a #PropertySources annotation in one file in a class that implements WebMvcConfigurerAdapter. There are two classes which contain an #Autowired Environment variable. One of these classes is itself a #Configuration class, and I would like it to have access to the fully-loaded Environment at the time it runs.
This isn't happening. When this code executes, the Environment is still null. I've tried reordering the #ComponentScan packages, tried moving the #PropertySources annotation, and nothing has helped me load the property sources in time.
I want this to happen first, before any other configuration.
What must I do to make it so?
UPDATE: After trying many things, including the Order annotation, I find the problem seems to be not so much that the #PropertySources are being loaded too late as that a class I have that is derived from org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer is being loaded too soon. Nothing in my code even references this class but Spring is somehow deciding that this, above all other classes, must be initialized first. No amount of messing around with #Order seems to change this. This in spite of the javadocs, which indicate that the behavior I want is the default:
Caveats
Subclasses of AbstractDispatcherServletInitializer will register their
filters before any other Filter. This means that you will typically
want to ensure subclasses of AbstractDispatcherServletInitializer are
invoked first. This can be done by ensuring the Order or Ordered of
AbstractDispatcherServletInitializer are sooner than subclasses of
AbstractSecurityWebApplicationInitializer.
You can use ContextInitializer, catch the moment when Boot prepared its environment and "inject" your property source programmatically as you want.
If you have a ConfigurableApplicationContext then it provides a ConfigurableEnvironment, which contains the propertySources as a list. If you want your PropertySource to rule all above the others than add it as first. If you want to place it to a special position then you can add it before an other, identified by its "name".
public class ConfigInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
#Override
public void initialize(ConfigurableApplicationContext ctx) {
// rule over all the others:
ctx.getEnvironment().getPropertySources().
addFirst(new ResourcePropertySource("file:/etc/conf/your_custom.properties"));
// rule over application.properties but not argument or systemproperties etc
ctx.getEnvironment().getPropertySources().
addBefore("applicationConfig: [classpath:/application.properties]",
new ResourcePropertySource("classpath:your_custom.properties"));
// names can be discovered by placing a breakpoint somewhere here and watch
// ctx.getEnvironment().getPropertySources().propertySourceList members,
// each has a name ...
}
}
You can bring into play this class by:
registering it in the application.properties :
context.initializer.classes=a.b.c.ConfigInitializer
or from application start :
new SpringApplicationBuilder(YourApplication.class).
initializers(new ConfigInitializer()).
run(args);
By the way this is a proper way to inject more of your custom properties, like properties coming from a database or a different host etc...
Not that I am an expert in Java config but maybe:
Spring 4 utilizes this feature in its #PropertySource annotation. To
remind you, #PropertySource annotation provides a mechanism for adding
a source of name/value property pairs to Spring's Environment and it
is used in conjunction with #Configuration classes.
Taken from: http://blog.codeleak.pl/2013/11/how-to-propertysource-annotations-in.html
Are you using #PropertySource or #PropertySources?
Have You tried 'order' property for spring bean initialisation?

What is the proper way to inject (via constructor) different types that implement that same interface?

For example, let's say I have an interface 'IFeed' and two concrete types ('Feed1' and 'Feed2') that implement this interface. Now let's say I have a 'FeedManager' type that takes multiple parameters that will get resolved dynamically, two of which are of type 'IFeed' and I'd like both concrete type to be injected via constructor injection, not via manual resolve (I only use resolve once at the composition root). I have a feeling that I should be using a factory but I wanted to see what the proper way of doing this might be. Many thanks in advance.
If you want ALL implementations of IFeed, you can use array syntax in your constructor and then nothing special is needed at type registration time.
container.RegisterType<IFeedManager, FeedManager>();
container.RegisterType<IFeed, FeedA>("FeedA"); // The name doesn't matter
container.RegisterType<IFeed, FeedB>("FeedB"); // The name doesn't matter
Then the manager constructor...
public FeedManager(IFeed[] feeds) {...}
or if you want to add a little flare for calling the constructor directly...
public FeedManager(params IFeed[] feeds) {...}
Assuming you want to determine the actual concrete instances at runtime, you need to use named type registrations and then tell unity which one you want. So, use a factory method to construct the types required and pass those in as parameter overrides. Unity will use the overrides and resolve any remaining dependencies.
// register the types using named registrations
container.RegisterType<IFeedManager,FeedManager>()
container.RegisterType<IFeed, Feed1>("Feed1")
container.RegisterType<IFeed, Feed2>("Feed2")
Assuming your feed manager has the following named constructor parameters
class FeedManager : IFeedManager
{
public FeedManager (IFeed Feed1, IFeed Feed2, string someOtherDependency)
{
}
}
and create your feed manager:
static IFeedManager CreateFeedManager()
{
ParameterOverride feed1 = new ParameterOverride("Feed1"
,_container.Resolve<IFeed>("feed1"));
ParameterOverride feed2 = new DependencyOverride("Feed2"
,_container.Resolve<IFeed>("feed2"));
IFeedManager = _container.Resolve<IFeedManager>(feed1,feed2)
return IFeedManager;
}
Obviously this is overly simplified, but you you insert your own logic to determine which instance is to be resolved and then injected for each of the IFeed instances required by the FeedManager.
With Unity you would do this like so:
container.RegisterType<IFeed, Feed1>("Feed1");
container.RegisterType<IFeed, Feed2>("Feed2");
container.RegisterType<FeedManager>(new InjectionConstructor(new ResolvedParameter<IFeed>("Feed1"),
new ResolvedParameter<IFeed>("Feed2")));
This has now configured Unity so that when it needs to resolve a FeedManager, it will resolve Feed1 for the first parameter and Feed2 for the second parameter.

Set Flash in Symfony 2.1

I have been adapting our code in preparation of moving our code to the new 2.1 Symfony codebase.
In 2.0.* we could set Flash messages by simply calling the session service in our controller using the following
$this->get('session')->setFlash('type', 'message');
I have trawled through the new documentation, I was just wondering if there was a clean way, similar to the above; rather than just calling the FlashBagInterface?
Try:
$this->get('session')->getFlashBag()->set('type', 'message');
Also, you might want to try the add() method instead, which won't obliterate other flash messages:
$this->get('session')->getFlashBag()->add('type', 'message');
FYI:
The Symfony HttpFoundation component has a very powerful and flexible session subsystem which is designed to provide session management through a simple object-oriented interface using a variety of session storage drivers.
FlashBagInterface has a simple API:
set(): Sets an attribute by key;
get(): Gets an attribute by key;
all(): Gets all attributes as an array of key => value;
has(): Returns true if the attribute exists;
replace(): Sets multiple attributes at once: takes a keyed array and sets each key => value pair;
remove(): Deletes an attribute by key;
clear(): Clear all attributes.
Source: Symfony2: Session Management

Resources