Spring cloud config server - how to add custom PropertySource visible in findOne() method of EnvironmentEncryptorEnvironmentRepository - spring-cloud

My goal is to add custom PropertySource to spring-cloud-server. What I want to achieve is to get some custom properties from that custom source in spring-cloud-config-client application.
Basing on suggestions from Adding environment repository in spring-config-server I've created spring-cloud-config-server application and separate project spring-cloud-config-custom. Second one is based on spring-cloud-consul-config code. So, I've created all necessary classes like CustomPropertySource, CustomPropertySourceLocator, CustomConfigBootstrapConfiguration and so on and configured them in spring.factories.
At the end, I've added maven dependency to spring-cloud-config-custom inside my spring-cloud-config-server.
So far so good. Everything works well. When I start server I can see that my CustomPropertySource is on the list of propertySources inside EnviromentRepository bean injected to EnvironmentController.
Problem: When I send GET request to #RequestMapping("/{name}/{profiles}/{label:.*}") (in EnvironmentController), injected EnviromentRepository bean is being used to find requested property source (repository.findOne(name, profiles, label) method).
Unfortunately my property source could not be found here. Why?
I've spent a lot of time on debugging this. I've found that repository delegates findOne() method call to other repositories: MultipleJGitEnvironmentRepository which delegates it to NativeEnvironmentRepository. Inside this delegates, findOne() method doesn't use propertySources from EnviromentRepository primary injected to controller. It creates new environment repository with new list of PropertySources and new separate SpringApplication. At the end, this list does not contain my CustomPropertySource and that is why findOne() returns empty propertySources in resulting Environment object.
Am I doing something wrong?
Is CustomPropertySourceLocator (and/or ConsulPropertySourceLocator) supposed to be used (autowired/bootstrapped) in spring-cloud-config-server or spring-cloud-config-client
Can spring-cloud-config-server deliver many different kind of PropertySources at the same time, via REST interface (saying "different" I mean all Git, Consul and Zookeeper)?

What you are doing is adding a property source to the config server itself, not the configuration it serves. Adding spring-boot-starter-actuator to your config server and viewing /env reveals:
{
"profiles": [
],
"server.ports": {
"local.server.port": 8888
},
"bootstrapProperties:custom": {
"test.prop3": "CUSTOM-VALUE-3",
"test.prop2": "CUSTOM-VALUE-2",
"test.prop1": "CUSTOM-VALUE-1"
},
}
To add something that will be served by config server, you have to implement an EnvironmentRepository.
Support for a composite EnvironmentRepository was recently added.

Related

How to set the offset.commit.policy to AlwaysCommitOffsetPolicy in debezium?

I created a Debezium Embedded engine to capture MySQL change data. I want to commit the offsets as soon as I can. In the code, the config is created including follows.
.with("offset.commit.policy",OffsetCommitPolicy.AlwaysCommitOffsetPolicy.class.getName())
Running this returns, java.lang.NoSuchMethodException: io.debezium.embedded.spi.OffsetCommitPolicy$AlwaysCommitOffsetPolicy.<init>(io.debezium.config.Configuration)
However, When I start the embedded engine with,
.with("offset.commit.policy",OffsetCommitPolicy.PeriodicCommitOffsetPolicy.class.getName()), the embedded engine works fine.
Note that the class OffsetCommitPolicy.PeriodicCommitOffsetPolicy constructor includes the config parameter while OffsetCommitPolicy.AlwaysCommitOffsetPolicy doesn't.
public PeriodicCommitOffsetPolicy(Configuration config) {
...
}
How to get the debezium embedded engine to use its AlwaysCommitOffsetPolicy?
Thanks for the report. This is partly bug (which we would appreciate if you could log into our Jira). You can solve this issue by calling a dedicated method embedded engine builder like `io.debezium.embedded.EmbeddedEngine.create().with(OffsetCommitPolicy.always())'
Tested with version 1.4.0Final:
new EmbeddedEngine.BuilderImpl() // create builder
.using(config) // regular config
.using(OffsetCommitPolicy.always()) // explicit commit policy
.notifying(this::handleEvent) // even procesor
.build(); // and finally build!

Grails mail plugin runtime configuration

Using grails mail plugin 1.0.7.
https://jira.grails.org/browse/GPMAIL-36 states that it's possible to change plguin configuration since 1.0.1 at runtime. Sadly it does not explains how to achieve it.
I want to be able to change the username at runtime to be able to use different mail accounts.
Thanks.
Based on this code, you should be able to change the configuration at runtime and the mail plugin will automagically re-deploy and update mail sender based on your changes.
Example:
Holders.config.grails.mail.username = 'foo'
Holders.config.grails.mail.password = 'bar'
sendMail {
to "foo#bar.com"
from "bar#foo.com"
subject "Hi"
body "This is an email"
}
Update:
It would appear that changing the configuration in this manner does not, in fact, fire the onConfigChange event. Per this, you can fire the event manually. Something like this:
Holders.pluginManager.getGrailsPlugin('mail').notifyOfEvent(GrailsPlugin.EVENT_ON_CONFIG_CHANGE, Holders.config)
I've realized this can be done accessing the mailSender bean from the context and updating it like is explained here
Changing mail configuration in runtime
However if #rmlan solution finally works it may be a much cleaner solution.
Actually thr rmlan solution works with the following fix. Since the onConfigChange compares hashCode of existing config map and new one, so if you set new configs in original configuration (Holders.config.grails.mail), then both configs are same and it never pass the condition to apply new changes, so a new structure should be created and pass it to notifyOfEvent method to mark the change as different hashCodes.
def mailConfig = [ grails: [ mail: [:] ] ]
mailConfig.grails.mail.host = newHost
mailConfig.grails.mail.port = newPort
Holders.pluginManager.getGrailsPlugin('mail').
notifyOfEvent(GrailsPlugin.EVENT_ON_CONFIG_CHANGE, mailConfig)
Still using async-mail and this one make the below exception
No qualifying bean of type [grails.plugin.mail.MailService] is defined: expected single matching bean but found 2: nonAsynchronousMailService,mailService
that is thrown because of the following part of onConfigChange
event.ctx.getBean(MailService.class).setPoolSize(mailConfig.poolSize?:null)
Commenting it let it works as a workaround, but making sendMail of mail plugin is called, not async-mail, so exception may raise if async-mail features is used on constructing mail. Hence to use async-mail in this workaround should use sendAsynchronousMail method.

Zend Framework 2 Override an existing Service?

I am using a zf2 module called GoalioRememberMe and now I want to override its service by my customized service. Or if it is not possible, I want to override the Module.php with my config. Is it possible?
In the Application module. I wrote this line in module.config.php:
'GoalioRememberMe\Service\RememberMe' => 'Application\Service\RememberMe'
Thanks in advance!
This is exactly the reason it is recommended to name the service as the type of the object that is returned. The object GoalioRememberMe\Service\RememberMe is named goaliorememberme_rememberme_service in the service manager. You can check that here.
So the solution is simple, instead of this:
'GoalioRememberMe\Service\RememberMe' => 'Application\Service\RememberMe'
Write this
'goaliorememberme_rememberme_service' => 'Application\Service\RememberMe'
As Jurian said, the service name is goaliorememberme_rememberme_service and it has been set in the getServiceConfig() method. So I wrote this code in the Module.php file in the Application Module:
$serviceManager->
setAllowOverride(true)->
setInvokableClass('goaliorememberme_rememberme_service', 'Application\Service\CustomRememberMe')->
setAllowOverride(false);
And it replaced successfully with my customized service!
Thanks very much to Jurian for the big help!
Actually the service manager first runs a method "canonicalizeName()" which "normalizes" the names as follows:
All _ / \ and - are stripped out
The key is made lowercase
Thus both "GoalioRememberMe\Service\RememberMe" and "goaliorememberme_rememberme_service" become "goalioremembermeremembermeservice" (i.e. they're both the same), thus the error message.
The quickest way to override an existing service is to create a *local.php or *global.php file in the /config/autoload folder. (That folder is identified in config/application.config.php.) Any override files in this folder are process after modules are loaded. If you have duplicate service manager keys, the last one wins.

How to obtain wicket URL from PageClass and PageParameters without running Wicket application (i.e. without RequestCycle)?

In my project, there are additional (non-wicket) applications, which need to know the URL representation of some domain objects (e.g. in order to write a link like http://mydomain.com/user/someUserName/ into a notification email).
Now I'd like to create a spring bean in my wicket module, exposing the URLs I need without having a running wicket context, in order to make the other application depend on the wicket module, e.g. offering a method public String getUrlForUser(User u) returning "/user/someUserName/".
I've been stalking around the web and through the wicket source for a complete workday now, and did not find a way to retrieve the URL for a given PageClass and PageParameters without a current RequestCycle.
Any ideas how I could achieve this? Actually, all the information I need is somehow stored by my WebApplication, in which I define mount points and page classes.
Update: Because the code below caused problems under certain circumstances (in our case, being executed subsequently by a quarz scheduled job), I dived a bit deeper and finally found a more light-weight solution.
Pros:
No need to construct and run an instance of the WebApplication
No need to mock a ServletContext
Works completely independent of web application container
Contra (or not, depends on how you look at it):
Need to extract the actual mounting from your WebApplication class and encapsulate it in another class, which can then be used by standalone processes. You can no longer use WebApplication's convenient mountPage() method then, but you can easily build your own convenience implementation, just have a look at the wicket sources.
(Personally, I have never been happy with all the mount configuration making up 95% of my WebApplication class, so it felt good to finally extract it somewhere else.)
I cannot post the actual code, but having a look at this piece of code will give you an idea how you should mount your pages and how to get hold of the URL afterwards:
CompoundRequestMapper rm = new CompoundRequestMapper();
// mounting the pages
rm.add(new MountedMapper("mypage",MyPage.class));
// ... mount other pages ...
// create URL from page class and parameters
Class<? extends IRequestablePage> pageClass = MyPage.class;
PageParameters pp = new PageParameters();
pp.add("param1","value1");
IRequestHandler handler = new BookmarkablePageRequestHandler(new PageProvider(MyPage.class, pp));
Url url = rm.mapHandler(handler);
Original solution below:
After deep-diving into the intestines of the wicket sources, I was able to glue together this piece of code
IRequestMapper rm = MyWebApplication.get().getRootRequestMapper();
IRequestHandler handler = new BookmarkablePageRequestHandler(new PageProvider(pageClass, parameters));
Url url = rm.mapHandler(handler);
It works without a current RequestCycle, but still needs to have MyWebApplication running.
However, from Wicket's internal test classes, I have put the following together to construct a dummy instance of MyWebApplication:
MyWebApplication dummy = new MyWebApplication();
dummy.setName("test-app");
dummy.setServletContext(new MockServletContext(dummy, ""));
ThreadContext.setApplication(dummy);
dummy.initApplication();

Multiple types were found that match the controller named 'Home'

I've just started using dotnetopenauth for my user registration. It's great, and is working perfectly.
The problem is now I'm getting an error when I try to go to /Home/ which says:
Multiple types were found that match the controller named 'Home'. This can happen if the route that services this request ('{controller}/{action}/{id}') does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter.
The request for 'Home' has found the following matching controllers:
OpenIdRelyingPartyMvc.Controllers.HomeController
YourApp.Controllers.HomeController
The problem is, I have no idea where OpenIdRelyingPartyMvc.Controllers.Homecontroller is coming from. I can't find ANY instance of "OpenIdRelyingPartyMvc" anywhere in my app, save 2 places, both of which occur in the UsersController:
OpenIdRelyingParty openid = new OpenIdRelyingParty();
I've tried deleting the DLL and rebuilding the app - no change. I can't figure out where this other controller would be.
Any ideas?
I had the same error message after changing the name and default namespace of the project.
Finally the solution was to manually delete all the files from debug -folder ("Clean Solution"-function of VS didn't help in this case).
My guess is that you copied the code from the samples into your codebase or you are referencing the DLL from the DotNetOpenAuth sample project. Note, OpenIdRelyingPartyMvc is the namespace of the MVC example.
So my suggestion is to first remove all instances of the DotNetOpenAuth library by starting from the project references.
use this in route.config file
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "ProjectName.Controllers" }
);
Note: Project Name which you had given while creating the project