How to keep generic filepath in #PropertySource annotation for both windows and linux - linux

I have following configuration code in my spring boot application:-
#Configuration
#PropertySources({
#PropertySource(value = "file://${CONFIG_PATH}/folder/application.properties"),
#PropertySource(value = "file://${CONFIG_PATH}/folder/application-log.properties"),
#PropertySource(value = "file://${CONFIG_PATH}/folder/application-persistence.properties"),
#PropertySource(value = "file://${CONFIG_PATH}/folder/application-environment.properties")
})
public class PopulateFixturesConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer
propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
Above code executes on Linux Server and I have Windows on local machine. So when I have to do development i have to change, I have to add extra "/" after file like this:
#PropertySource(value = "file:///${CONFIG_PATH}/folder/application-environment.properties")
and again when i have to commit the code i have to remove that extra "/".
Is there any way to keep the path generic for both windows and linux.
Thanks,

If you are using Java greater than Java 7, then you can do like this
String configPath= System.getProperty("CONFIG_PATH");
java.nio.file.Path path = java.nio.file.Paths.get(configPath, "some", "dir", "path1", "path2")
java.nio.file.Path have lot of methods which can give you the absolute path in string
If you are using Java less than Java 7 then use File.separator

Related

How to make app settings in .NET Core that translate to Azure app settings?

I can't remember where I saw this but I followed the advice on a blog when setting up my app configuration for my .NET Core MVC application. I created a model like this to hold some settings my app needed:
public class BasePathSettings
{
public string BaseImageFolder { get; set; }
public string BaseApiUrl { get; set; }
}
My StartUp has this...
public void ConfigureServices(IServiceCollection services)
{
...
// this adds the base paths to container
services.Configure<BasePathSettings>(Configuration.GetSection("BasePathSettings"));
....
}
And the appsettings.json has this in it:
"BasePathSettings": {
"BaseImageFolder": "D:\\Images\\",
"BaseApiUrl": "http://localhost:50321/"
},
I inject the controllers that need this info like so....
private readonly BasePathSettings _settings;
public ClientsController(IOptions<BasePathSettings> settings)
{
_settings = settings.Value;
_client = new HttpClient();
_client.BaseAddress = new Uri(_settings.BaseApiUrl);
}
Running this on my localhost everything runs fine.
However, when I deploy this application to Azure I assumed I needed to create an application setting in the General Settings of the app service. So I made an app setting called BasePathSettings and copied the json for the setting into the value:
{ "BaseImageFolder": "imagePath", "BaseApiUrl": "apiUrl" }
It appears that Azure barfs when it's in the ConfigureServices code claiming that the web.config does not have the correct permissions in NTFS. I'm guessing the real culprit is how the json value is being read from the Azure application settings.
Can I even use json there? If so, does it need formatted differently?
Can I even use json there? If so, does it need formatted differently?
To add hierarchical structure settings to Azure web app, we could place a colon between the section name and the key name. For example,
use BasePathSettings:BaseImageFolder to set your folder
use BasePathSettings:BaseApiUrl to set your url
I made an app setting called BasePathSettings and copied the json for the setting into the value
Format should be -
basepathsettings:baseimagefolder (just single slash)
basepathsettings:baseapiurl
If you try to define "BasePathSettings" in a single WebApp setting that takes a json value, the GetSection will return null.
As a workarround, I use this extension method as a replacement of GetSection() :
public static T GetWebAppSection<T>(this IConfiguration config, string key)
where T:class
{
T configValue = config.GetSection(key).Get<T>();
if(configValue == default(T))
{
configValue = JsonConvert.DeserializeObject<T>(config[key]);
}
return configValue;
}

Revit Api Load Command - Auto Reload

I'm working with the revit api, and one of its problems is that it locks the .dll once the command's run. You have to exit revit before the command can be rebuilt, very time consuming.
After some research, I came across this post on GitHub, that streams the command .dll into memory, thus hiding it from Revit. Letting you rebuild the VS project as much as you like.
The AutoReload Class impliments the revit IExteneralCommand Class which is the link into the Revit Program.
But the AutoReload class hides the actual source DLL from revit. So revit can't lock the DLL and lets one rebuilt the source file.
Only problem is I cant figure out how to implement it, and have revit execute the command. I guess my C# general knowledge is still too limited.
I created an entry in the RevitAddin.addin manifest that points to the AutoReload Method command, but nothing happens.
I've tried to follow all the comments in the posted code, but nothing seems to work; and no luck finding a contact for the developer.
Found at: https://gist.github.com/6084730.git
using System;
namespace Mine
{
// helper class
public class PluginData
{
public DateTime _creation_time;
public Autodesk.Revit.UI.IExternalCommand _instance;
public PluginData(Autodesk.Revit.UI.IExternalCommand instance)
{
_instance = instance;
}
}
//
// Base class for auto-reloading external commands that reside in other dll's
// (that Revit never knows about, and therefore cannot lock)
//
public class AutoReload : Autodesk.Revit.UI.IExternalCommand
{
// keep a static dictionary of loaded modules (so the data persists between calls to Execute)
static System.Collections.Generic.Dictionary<string, PluginData> _dictionary;
String _path; // to the dll
String _class_full_name;
public AutoReload(String path, String class_full_name)
{
if (_dictionary == null)
{
_dictionary = new System.Collections.Generic.Dictionary<string, PluginData>();
}
if (!_dictionary.ContainsKey(class_full_name))
{
PluginData data = new PluginData(null);
_dictionary.Add(class_full_name, data);
}
_path = path;
_class_full_name = class_full_name;
}
public Autodesk.Revit.UI.Result Execute(
Autodesk.Revit.UI.ExternalCommandData commandData,
ref string message,
Autodesk.Revit.DB.ElementSet elements)
{
PluginData data = _dictionary[_class_full_name];
DateTime creation_time = new System.IO.FileInfo(_path).LastWriteTime;
if (creation_time.CompareTo(data._creation_time) > 0)
{
// dll file has been modified, or this is the first time we execute this command.
data._creation_time = creation_time;
byte[] assembly_bytes = System.IO.File.ReadAllBytes(_path);
System.Reflection.Assembly assembly = System.Reflection.Assembly.Load(assembly_bytes);
foreach (Type type in assembly.GetTypes())
{
if (type.IsClass && type.FullName == _class_full_name)
{
data._instance = Activator.CreateInstance(type) as Autodesk.Revit.UI.IExternalCommand;
break;
}
}
}
// now actually call the command
return data._instance.Execute(commandData, ref message, elements);
}
}
//
// Derive a class from AutoReload for every auto-reloadable command. Hardcode the path
// to the dll and the full name of the IExternalCommand class in the constructor of the base class.
//
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
[Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
public class AutoReloadExample : AutoReload
{
public AutoReloadExample()
: base("C:\\revit2014plugins\\ExampleCommand.dll", "Mine.ExampleCommand")
{
}
}
}
There is an easier approach: Add-in Manager
Go to Revit Developer Center and download the Revit SDK, unzip/install it, the check at \Revit 2016 SDK\Add-In Manager folder. With this tool you can load/reload DLLs without having to modify your code.
There is also some additional information at this blog post.
this is how you can use the above code:
Create a new VS class project; name it anything (eg. AutoLoad)
Copy&Paste the above code in-between the namespace region
reference revitapi.dll & revitapiui.dll
Scroll down to AutoReloadExample class and replace the path to point
your dll
Replace "Mine.ExampleCommand" with your plugins namespace.mainclass
Build the solution
Create an .addin manifest to point this new loader (eg.
AutoLoad.dll)
your .addin should include "FullClassName" AutoLoad.AutoReloadExample
This method uses reflection to create an instance of your plugin and prevent Revit to lock your dll file! You can add more of your commands just by adding new classes like AutoReloadExample and point them with seperate .addin files.
Cheers

How to get the full path of a file inClass library?

I am writing a class library and referring it in a WCF Service.
In this class library , i need to get the physical path of the app.config file.
It is working when hard coded with full physical path. But, i do not want to do this way.
Please see my code:
private static void loadConfig()
{
strConfigpath = "app.config";
log4net.Config.XmlConfigurator.Configure(new FileInfo(Path.GetFullPath(strConfigpath)) );
}
I tried using Path.GetFullPath(). But, it is giving wrong result.
I cannot use Server.MapPath() since it is not a web service or web application.
How to do this ? Ant thoughts or suggestions ?
Use the FullName property
string fileName = "app.config";
FileInfo f = new FileInfo(fileName);
string fullname = f.FullName;
f.DirectoryName; //This will give the folder path which is having the file
try something like this,
string folder = System.Web.HttpContext.Current != null ?
System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App_data") : System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
refered : Get the file path of current application's config file

Trying "Messaging via attribute" from the documentation

I'm trying to get the hung of catel but have a problem.
Trying "Messaging via attribute" gets an compile error.
'Catel.MVVM.ViewModelBase.GetService(object)' is obsolete: 'GetService is no longer >recommended. It is better to inject all dependencies (which the TypeFactory fully supports) >Will be removed in version 4.0.0.'
private void OnCmdExecute()
{
var mediator = GetService<IMessageMediator>();
mediator.SendMessage("Test Value");
}
[MessageRecipient]
private void ShowMessage(string value)
{
var messageService = GetService<IMessageService>();
messageService.Show(value);
}
I'm using 3.9.
A hint and a code snippet whould be good help.
Thanks for your attention.
The GetService is marked obsolete. You have 2 options:
1) If you are using a view model, simply let the services be injected in the constructor:
private readonly IMessageMediator _messageMediator;
private readonly IMessageService _messageService;
public MyViewModel(IMessageMediator messageMediator, IMessageService messageService)
{
Argument.IsNotNull(() => messageMediator);
Argument.IsNotNull(() => messageService);
_messageMediator = messageMediator;
_messageService= messageService;
}
2) Use the GetDependencyResolver extension method:
var dependencyResolver = this.GetDependencyResolver();
var messageMediator = dependencyResolver.Resolve<IMessageMediator>();
Solution 1 is the recommended way.
Thanks for your answer.
I also found a good example in the "Catel.Examples" solution, link to download

How do I set an embedded Groovy scripts classpath?

I am trying to extend an Eclipse code builder (for generating DTOs from Hibernate VOs) - and it uses Groovy for its template system.
The code it uses to create the groovy Script is a little weird (not what I see in the Groovy docs) but it works, mostly:
GroovyShell shell = new GroovyShell();
script = shell.parse(source);
Then, later:
Binding binding = (bindings == null ? new Binding() : new Binding(bindings));
Script scriptInstance = InvokerHelper.createScript(script.getClass(), binding);
scriptInstance.setProperty("out", out);
scriptInstance.run();
out.flush();
Now, this works just fine, until it hits a reference to an object that is not directly in the project. In the script, it iterates through the properties of the Class that it is processing - when it does this, Groovy looks at all of the methods and when it can't find a Class definition for one of the method parameters, it craps out. In this case, it's dying when it finds any references to Hibernate, but I'm sure it will crap out with a lot more. It doesn't need to do anything to them, but it can't live without knowing what they are apparently.
Script doesn't appear to have a classloader that I can supply any classpath info, so I tried providing it to the GroovyShell - no difference.
What's the proper way to fix this so that the Groovy interpreter can find my projects referenced Jars?
I had this exact problem and solved it by creating my own URLClassLoader, and using reflection to call a protected method to add a new path to the ClassPath
// Specify the path you want to add
URL url = new URL("file://path/to/classes/here");
// Create a new class loader as a child of the default system class loader
ClassLoader loader = new URLClassLoader(System.getClass().getClassLoader());
// Get the AddURL method and call it
Method method = URLClassLoader.class.getDeclaredMethod("addURL",new Class[]{URL.class});
method.setAccessible(true);
method.invoke(loader,new Object[]{ url });
GroovyShell shell = new GroovyShell( loader );
The same as #James can be done without using reflection, loading all jar files from a certain folder:
URLClassLoader classLoader = new URLClassLoader( getExtraJarUrls(), getClass().getClassLoader() );
GroovyShell shell = new GroovyShell( classLoader, binding, compilerConfiguration );
private URL[] getExtraJarUrls() throws MalformedURLException
{
logger.debug( "Loading extra jars from {}", EXTRA_JARS_DIR.getAbsolutePath() );
URL[] result;
File[] files = EXTRA_JARS_DIR.listFiles( new JarFilenameFilter() );
if (files != null)
{
List<URL> urls = new ArrayList<URL>( files.length );
for (File file : files)
{
urls.add( file.toURI().toURL() );
}
result = urls.toArray( new URL[urls.size()] );
}
else
{
result = new URL[0];
}
logger.debug( "Adding URLs to classloader: {}", Arrays.toString( result ) );
return result;
}
private static class JarFilenameFilter implements FilenameFilter
{
public boolean accept( File dir, String name )
{
return name.endsWith( ".jar" );
}
}
I'm having the same problem trying to automate Gant scripts running. The solution I found is:
copy gant-starter.conf (or
groovy-starter.conf if it's just
groovy) from $GROOVY_HOME/conf to your
own dir;
add "load [directory]" or
"load [jar]" there, as described in
javadocs to
org.codehaus.groovy.tools.LoaderConfiguration,
found in Groovy source distribution;
before starting groovy set
groovy.starter.conf.override system
property to the name of that file,
like
-Dgroovy.starter.conf.override=[filename]

Resources