I'm using a rest service with AndroidAnnotations, configured like so:
#Rest(rootUrl = "http://192.168.1.48:8080/stuff/services/rest/StuffService/",
converters = {MappingJacksonHttpMessageConverter.class})
public interface IStuff
{
#Post("fetchAllStuff")
public Response fetchAllStuff(Request req);
}
So what happens when I need to change the URL at runtime? If the URL is hard-coded in the annotation, what would I do to change it? Is there some way I could have it in a properties or XML file as well?
As explained on the wiki, you can simply define a void setRootUrl(String rootUrl) method and it will be generated as a setter on the final class
Related
I have this application.properties:
url.up=${url:http://localhost:8080/upload}
And I want to extract the url "http://localhost:8080/upload". How can I extract it?
I tried something like this, but the url is null:
String url = config.getPropertyValue("url");
Where getPropertyValue:
public String getPropertyValue(String propertyKey) {
return properties.getProperty(propertyKey);
}
U can use #Value in your class
in your property file U can define
url.up=http://localhost:8080/upload
In Your class
#Value("${url.up}")
private String url;
then U can access the value using variable url
Unfortunately I do not know what class the config object is instatiated from which makes it hard to understand what the properties.getProperty() method call is doing. Therefore, I'll give you a a more general answer. As you are using Spring, you basically have two very elegant solutions to retrieve data from your application property files. If you just need a single value (as in your example the url.up field), then you would typically directly inject that value into the class that needs this data as in the following short Kotlin snippet (in java this would be very similar, just look up the #Value annotation on the internet).
#Component
class PropertyPrinter(
#Value("\${url.up}") private val url: String
) {
#PostConstruct
fun postConstruct() {
println("URL is: $url")
}
}
The other way would be to create a dedicated config class that hold a bunch logically connected fields and add the #ConfigurationProperties annotation. See here for a more in depth explanation.
You should use #Value annotation. For example:
#Value("${url}")
private String url;
The url variable holds http://localhost:8080/upload.
You should use #Value or appContext:
https://stackoverflow.com/a/29744955/21233858
in my project it's necessary to inject a value from the application.properties file, profile-dependent, into the endpoint-class to the namespace-variable of the #PayloadRoot annotation.
The problem: the namespace-value must be a constant and in spring I can't inject a value into a final variable.
I find an advice to inject in this way:
#PayloadRoot(namespace = "${my.namespace}", localPart = "getMyRequest")
#ResponsePayload
public JAXBElement<MyResult> myMethod(#RequestPayload JAXBElement<MyInput> request) {
but ... it doesn't work.
Has anyone a working solution?
Thanks...
You could do one of the following:
1) Use reflection once you have the appropriate value (but you need to make sure that you set the value before the endpoint mapping occurs): example here
2) Extends the class PayloadRootAnnotationMethodEndpointMapping and in the method getLookupKeysForMethod, use a custom a method getQNameFromAnnotation where you will inject the correct value of the namespace.
private QName getQNameFromAnnotation(PayloadRoot payloadRoot) {
return new QName(/*INJECT YOURNAMESPACE HERE*/, payloadRoot.localPart());
}
I am working on a project that uses dropwizard's hibernate bundle to get a session factory per the below docs:
http://www.dropwizard.io/0.7.1/docs/manual/hibernate.html
The project doesn't use any xml and only uses annotated classes for the configuration of the bundle just like in the example.
public class ExampleConfiguration extends Configuration {
#Valid
#NotNull
#JsonProperty("database")
private DataSourceFactory database = new DataSourceFactory();
public DataSourceFactory getDataSourceFactory() {
return database;
}
}
private final HibernateBundle<ExampleConfiguration> hibernate =
new HibernateBundle<ExampleConfiguration>(
some.class
) {
#Override
public DataSourceFactory getDataSourceFactory(ExampleConfiguration configuration) {
return configuration.getDataSourceFactory();
}
};
However, we have a use case where I need to prepend the environment to the table name of the DAO objects such that the #Table annotation gets overwritten.
I have a class which implements ImprovedNamingStrategy, per the below docs
http://docs.jboss.org/hibernate/orm/5.0/javadocs/org/hibernate/cfg/ImprovedNamingStrategy.html
But how do I hook the naming strategy into my dropwizard hibernate bundle. I would like to be able to do something like this...
hibernateBundle.setNamingStrategy(ImprovedNamingStrategy.Instance)
or
hibernateBundle.addAnnotatedClass(someHibernateNamingPropertyConfig)
https://docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/cfg/Configuration.html#setNamingStrategy(org.hibernate.cfg.NamingStrategy)
However, the hibernateBundle API doesn't allow for any of this.
Looking through the source code of HibernateBundle
https://github.com/dropwizard/dropwizard/blob/master/dropwizard-hibernate/src/main/java/io/dropwizard/hibernate/HibernateBundle.java
You can see that it uses "import io.dropwizard.Configuration;" as opposed to org.hibernate.cfg which does expose all of these methods. I'm trying to avoid a major refactor so if there is a "hacky" way to force set the naming property on the bundle, then I'm okay with that.
Any ideas of where to go from here would be much appreciated.
Found a solution for this that works for me in Dropwizard 0.8.4. Not sure if it can help you with Dropwizard 0.7.1, but it will definitely be helpful for readers coming from Google with the same question.
You can extend HibernateBundle and override configure(). This method is called just before SessionFactoryFactory is going to be built, with the Configuration object for it. You can then override the method to add any special configurations you might need.
Example:
public abstract class DatabaseWithImprovedNamingStrategyBundle extends ScanningHibernateBundle {
public DatabaseWithImprovedNamingStrategyBundle(String pckg) {
super(pckg);
}
#Override
protected void configure(Configuration configuration) {
super.configure(configuration);
configuration.setNamingStrategy(ImprovedNamingStrategy.INSTANCE);
}
}
This example uses ScanningHibernateBundle because it's the one I was using, but you can use HibernateBundle directly too.
I just decided not to use the Hibernate Bundle and create a second config object which reads values out of the Hibernate Bundle.
I have two java files that contain endpoints that deal with file management. One is called FileResource.java and the other is DirectoryResource.java. DirectoryResource.java has only one method, which is createDirectory. I need to move that method over to FileResource.java and remove DirectoryResource.java completely.
The problem is that the endpoint for the createDirectory method is currently /api/dir/create. When I move it over to FileResource.java it won't work anymore because the class-level #Path annotation is at "/file/" instead of "/dir/".
Here's my question: Is it possible to override the #Path annotation on the method so that I can to maintain the endpoint /api/dir/create after moving it to the FileResource class?
I want to make sure that those who are using the api don't have to refactor their code to point to a new endpoint.
//FileResource.java
...
#Path("/file/")
public class FileResource() {
#POST
#Path("create")
public Response createFile(String fileContent) {
...
return Response.ok().build();
}
...
}
//DirectoryResource.java
...
#Path("/dir/")
public class DirectoryResource() {
#POST
#Path("create")
public Response createDirectory(String path) {
...
return Response.ok().build();
}
...
}
There's no 'overriding' of #Path annotation. They add.
Method annotated with #Path("create") in the class annotated with #Path("dir") will resolve to /dir/create.
You define the path by defining correct methods in correct channels. You move methods and delete channels only if you need to change pathes.
I see no reason you need to change the channel without changing the API, but if you still need to, you should play, for example, with mod_rewrite on Apache. But I'd advise against it. Just keep your channels structure clean.
how to change/set a binding by a property/string given in a property/text file? in my case i want to implement a kind of "demo mode".
In normal mode a property gives an url to an external service but if url is "demo" the binding of the according interface should be changed like this:
normal:
bind(SasDatenProvider.class).to(SasDataProviderHttpImpl.class);
demo
bind(SasDataProvider.class).to(SasDataProviderFileImpl.class);
how to achieve that?
thx in advance
You can use a method annotated with #Provides in your module. Then you can do something like this:
public class MyModule extends AbstractModule {
#Provides
SasDatenProvider provideSas(SasDataProviderHttpImpl http,
SasDataProviderFileImpl file){
boolean isDemo = false; /* do you property lookup logic here */
return isDemo ? file : http;
}
}
You can read more about #Provides-methods in the guice docs:
http://code.google.com/p/google-guice/wiki/ProvidesMethods
If your don't want this kind of logic in you module, you can consider creating your own provider:
http://code.google.com/p/google-guice/wiki/ProviderBindings