org.springframework.core.env.Environment along with #ConfigurationProperties - properties

When a properties file is placed externally, then can we use org.springframework.core.env.Environment to access that properties file?
#Autowired
public Environment env;
String propertyValue= env.getProperty(key);
Any example/tutorial link will be helpful.
I have seen how #ConfigurationProperties can be used with #PropertySource, but here the properties file is at an external location and I want to use Environment instead of a POJO with #Component

Related

How do I configure the default ObjectMapper?

In light-4j config module, there is an ObjectMapper instance that is used in a lot of different places. I have a Rest/GraphQL hybrid application and want to customize the default ObjectMapper. What is the best way to do so?
The ObjectMapper instance in the config module is static variable and a static block is used to initialize it. To overwrite the configuration, you can create a startup hook to do that.
Config.getInstance().getMapper()
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.enable(MapperFeature.USE_STD_BEAN_NAMING)
.setSerializationInclusion(JsonInclude.Include.ALWAYS)
.setPropertyNamingStrategy(new CobraCase())

Is there a symbolic item to reference spring-cloud config server?

A project I'm working on is utilizing Spring Cloud Config server to handle property update/refresh.
One question that has repeatedly come up is how to reference/serve plain text from the config server.
I know that the server supports serving plain-text. What I'm trying to figure out is that if I have a reference /foo/default/master/logj42.xml.
How would I reference this in an "agnostic" way such that if I were to put:
{configserver}/foo/default/master/log4j2.xml in the config file
The reference {configserver} would be expanded.
Additionally, when using "discovery", if I inject the reference to the "resource" as above, the default mechanism will attempt to use java.net.URLConnection to load the content. I do not think it will resolve the 'discovery' host.
Thanks in advance.
It also can be resolved using Customizing Bootstrap Configuration without aspects by creating custom property source and set configserver uri after locating from discovery.
I had similar issue, more details in this stackoverflow post
I found a way to do this that is minimally invasive but "pierces the veil" of where the config server actually resides.
On the primary application class, the annotation #EnableDiscoveryClient needs to be added.
I created an aspect to add a property source with a key that indicates the actual URI of the server handling the request:
#Component
#Aspect
public class ResolverAspect {
#Autowired
private DiscoveryClient discoveryClient;
#Pointcut("execution(org.springframework.cloud.config.environment.Environment org.springframework.cloud.config.server.environment.EnvironmentController.*(..))
private void environmentControllerResolve();
#Around("environmentControllerResolve()")
public Object environmentControllerResolveServer(final ProceedingJoinPoint pjp) throws Throwable {
final Environment pjpReturn = (Environment)pjp.proceed();
final ServiceInstance localSErviceInstance = discoveryClient.getLocalServiceInstance();
final PropertySource instancePropertySource =
new PropertySource("cloud-instance", Collections.singletonMap("configserver.instance.uri", localServiceInstance.getUri().toString()));
pjpReturn.addFirst(instancePropertySource);
return pjpReturn;
}
}
By doing this, I expose a key configserver.instance.uri which can then be referenced from within a property value and interpolated/resolved on the client.
This has some ramifications with regard to exposing the actual configuration server, but for resolving resources that do not necessarily utilize the discovery client this can be utilized.

Autofac how to pass configuration settings to base class

Currently I am using Autofac as IoC.
I would like to pass configuration (appsettings) to my base class through I am calling rest services.
current structure is
class baseclass{
public baseclass(logger){}
}
class derivedclass : baseclass{
public derivedclass(IService service):base(logger)
{
}
}
there are more than 50 classed where i am refering baseclass so dont want to pass configuration for each one.
Can you please help to find solution.
Thanks
I assume that you don't want to change derived constructors to pass through your configuration. So you have some options:
Inject your configuration to your base class by property
Live without dependency injection (directly access to ConfigurationManager or some Service Locator pattern).
Although both options are bad practices and I recommend you to inject your configuration through constructors.

How do I use Enterprise Library to specify config for only one DLL or subsystem?

How can I use EL to specify trace listeners and formatters for only one subsystem (say, DLL) of a large system?
I'm writing a sub-module of a very large large application (thick client, not web app) that uses a gateway/portal model to load its various subsystems. I'd like use EL 5.0 (already in use) to manage logging/tracing configuration, but just for my subsystem. It looks like app.config is getting converted by VS to foo.dll.config. Can I convince EL to pick up the settings in foo.dll.config (at run-time) and merge them into its existing configuration data, in memory? (Not into a merged config file.)
(Looks like, based on Enterprise Library Class Library App.Config, it can't be done.)
I wouldn't recommend trying to merge configuration -- it can can get messy.
Instead, I would configure your sub-module to configure and use private references to the appropriate Enterprise Library objects you need.
I'm assuming your module is a class library that has an app.config. When compiled it generates a module.dll.config file in the output directory. To take an example of logging using Enterprise Library 6, I would create a helper class to load your own configuration and maintain a reference to your module's LogWriter. In this way your module loads its own configuration and does not interfere and is not influenced by other configuration in the application.
namespace MyModule
{
public class MyModuleClass
{
public void DoSomething()
{
MyModuleLogger.LogWriter.Write("MyModule Test", "General");
}
}
public static class MyModuleLogger
{
private static Lazy<LogWriter> logWriter = new Lazy<LogWriter>(() =>
{
FileConfigurationSource configSource =
new FileConfigurationSource("MyModule.dll.config");
LogWriterFactory factory = new LogWriterFactory(configSource);
return factory.Create();
});
public static LogWriter LogWriter
{
get { return logWriter.Value; }
}
}
}
I've used a static class but you could use a variety of approaches that may fit with your design (singleton, factory, etc.)
You will have to ensure that your dll.config file is deployed along with your assembly. You could also hit problems if there are version issues with Enterprise Library (e.g. you are using Version 6 while the application uses Version 5.)

Custom collection type is not being reused on WCF client Proxy side issue

I have defined the following type in a class library project.
[CollectionDataContract()]
public class OperationException:System.Collections.Generic.Dictionary<string,ExceptionData>
{
[DataMember()]
public bool ExceptionExists { get; set; }
}
[DataContract()]
public class ExceptionData {[DataMember()] public string Msg;}
On my WCF service end, I am returning an object which contains the above class as a child member variable like this.
[DataContract()]
public class SaveClient
{
[DataMember()]
public string Id;
[DataMember()]
public OperationException ExceptionCollection;
}
I have the OperationException class library referenced on the client side. The problem is when I generate the proxy using Add Service Reference, a new definition of OperationException of type dictionary is generated. I do have the Reuse Types option set to true. I like to have Actual 'OperationException' type being used since I have to pass this object to other methods.
Thanks in Advance..!
Iftikhar.
I had the same issue and like you I had applied the CollectionDataContract attribute and told the proxy generator to reuse types from my shared assembly.
The fix was not obvious, you need to supply a hook in the Reference.svcmap file on your client to tell the generator to use your custom collection type.
In Reference.svcmap edit the CollectionMappings element as follows and then update the service reference:
<CollectionMappings>
<CollectionMapping TypeName="YourSharedAssemblyNamespace.OperationException" Category="List" />
</CollectionMappings>
I think the same objective can be achieved if you are using svcutil from the command line by supplying the collection type argument.
/collectionType:YourSharedAssemblyNamespace.OperationException
See these posts for more info:
http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/09eefbbc-bf63-4aa3-a0cb-01a9dbd7f496/
http://www.codeproject.com/KB/WCF/WCFCollectionTypeSharing.aspx
I am not sure why the WCF proxy generator doesn't just use it's common sense to find the shared collection types but there you go, chalk it up as another funny from the WCF tool design.
Does your client proxy assembly have a project reference to the class library where the type is added?
If the proxies generated by svcutil are not what you want, it's also very easy to write them by hand. Just create your own ClientBase-derived class and implement your service interface on it. Then you have control over which assembly types you want to reuse.