Spring - Binding web form to application.properties file - java

I have a web form that enables one to update the appliaction.properties, so that user does not have to go to the file and edit it. I wants to load the value from the application.properties file and display in the web form textfield. After the user edit the some changes, user can update the application.properties file.
Question - How can I bind my web form to application.properties file other than using #value in Spring? As the key/value pairs might be updated through web form, I believe #value is not the right choice.

The application properties are for the settings the application needs to load when it starts up, and then connects to a database for example, with the username and password specified in that file (although environment variables can also be used.)
You shouldn't really edit this file at run-time, with the exception of using the Refresh Scope annotation. But I don't advise you do that as it's fairly hard in practice to achieve an application which supports changing configuration at run-time.
There is also Spring Cloud Config server for reloading properties at run-time and that provides a REST API although you mainly just use git with that one.
But the key is here that they are all mentioning configuration which is only something developers do. I also don't think you want to use the filesystem for storing your state, much rather have database. There are many reasons to use a file system over a database I won't go into them now.
I will make the assumption you are a beginner looking at your rep. Best advice I can give you is to watch what everyone else is doing and learn from that first. Most of the time people are all doing similar things because it is the right thing to do. If you can't find anybody else changing properties files based on form submissions in their spring app but rather using databases you probably want to go with the database.

We were in a similar situation last month where client need update in configuration file in run time.
We created a central Spring component that loads all properties from file using #Value
#Component
public class ConfigurationManagerComponent{
#Value("conf.username")
private String userName;
#Value("conf.email");
private String email;
/*
* All your attributes
*/
//getters and setters
public String getUserName(){
return this.userName;
}
public void setUserName(String userName){
// first set the value to this class (component)
this.userName=userName;
//second save this value in the properties file
//a specific method you have to implement
saveproperties("conf.username",userName);
}
/*
* Do like this for all your getters and setters
*/
}
Then, in any time you need to get or save properties, just inject this component and use its getters and setters
#Autowired
ConfigurationManagerComponent configComponent;
String myActualUserName=configComponent.getUserName();
So then you can get all your data in your controller from config component and set them to your spring model to fill form in webpage, and when saving after edit, you can always use setters of your config component(update class and properties file).
This method is not a standard, just a solution we employed to resolve a problem, it's giving good results right now.
You can also check Apache commons configuration Here for other solutions..
Hope this will help.

Related

How to use Basic Authentication with Spring's Resource abstraction

I have a file on a server available via Https I want to access using Spring's Resource abstraction. I want Spring to resolve the resource and inject it into the constructor of my Bean like this:
public class MyClass {
public MyClass(
#Value("https://myserver.com/myfile") Resource resource) {
// do something using the resource
}
}
The issue is that I cannot figure out how to include the username and password for basic authentication into this pattern. I tried the "common" style
#Value("https://username:password#myserver.com/myfile")
but it looks like this is not understood correctly. The server is responding with HTTP status 401 - Unauthorized. I copied the string and perfomed the same query using wget and it worked. So there is no issue with my credentials but most likely with the syntax used to define the resource.
Is there a valid syntax for this in Spring or must I fetch the config in an alternative way setting the Authentication header by hand?
This feels wrong, and I'd prefer it if you didn't do it this way...but you can rely on #Value to inject the property value. Note the use of #Autowired here.
#Component
public class MyClass {
private String resourceUrl;
#Autowired
public MyClass(#Value(${external.resource.url}) String resourceUrl) {
this.resourceUrl = resourceUrl;
}
// The rest of your code
}
Then you could place into the property external.resource.url whichever value you liked...including your full URL with username and password.
I want to call attention that this is probably not a desirable thing to do, since you want to be able to inject the URL, username and password as separate things into your application. This gives you an idea of how you can accomplish it with one component, and while I strongly encourage you to split this up instead (and whatever you do, do not check the properties file in with those values into your source control), I leave the mechanical part of splitting this into more values as an exercise for the reader.

Create new static address dynamically in Java web application

When developing a Web Application in Java, launching in Tomcat, I need to be able to create (dynamically) a new static address (link,URL) in the server that will be used to view the information of a new item, let's call it new_item_001, which have been just created by one user.
Say I want to create a new address
www.domain.com/webapp/items/new_item_001
which can be used to render a view of the contents of new_item_001.
Which is the best approach to do this?
Should I dynamically create a new servlet class for this view?
Should I dynamically create the folder items and one html file new_item_001 for this item inside of it?
Should I edit the server address mapping rules to create this static address and map it to a central servlet which somehow knows which item to display?
I understand the question is ill posed, and that I am far from even understanding the issue, so I would like some guidelines on what to look for.
None of the above.
You should simply have a servlet mapped to /items/*. When a request come to this servlet, analyze the actual path of the request, extract the part after /items/ to know the actual value (new_item_001) in your example, get the data corresponding to this item from the database, and send it to the browser.
Using a true MVC framework like Spring MVC would make that much easier. You could simply map a method of a controller using
#RequestMapping("/items/{itemId}")
public Item getItem(#PathVariable("itemId") String itemId) {
...
}
and let the framework do all the URL parsing for you.
I would like to tackle this in a simple way. Creating a servlet for each created item would be overkill and become quite cumbersome to manage after a successful run of the application for some time.
Changing/editing server mapping URL looks very naive approach and is not scaling too. Let configuration be there and change them only when you actually need to change them.
My suggestion is to create one servlet that handles all these requests. For example, you may save item information on a datastore or on file system(i.e images uploaded by user etc..). Next time a GET request is received by the application to fetch saved information of an item, servlet should be able to reference the item on database associated with the item id on the URL. If you don't wish to expose item id/surrogate key in the database, you can also have a simple mapping between them by implementing your own logic. Frameworks like Spring MVC do a good job in mapping URLs to resources like this should you wish to use a framework.
Additionally to minimize the number of requests to the same item, you can also implement an HTTP caching strategy(i.e. ETAG, If-Modified-Since) by instructing your web server at the time of first GET request from a user.

Play Framework 2.1: Overriding configuration file programmatically in Global settings

I'm working to develop a multi-tenant Play Framework 2.1 application. I intend to override the onRequest method of the GlobalSettings class to load and set a custom configuration based on the subdomain of the request. Problem is, I don't see how this would be possible in Play 2.x.
I can override system properties at the command line when starting the server, but how can I do this programmatically in Java code for each request?
The code would look something like this (I assume):
#Override
public play.mvc.Action onRequest(Request request, Method actionMethod) {
//Look up configuration settings in Cache based on request subdomain
//(i.e. Cache.get("subdomain.conf"))
//if not in cache:
//load appropriate configuration file for this subdomain (java.io.File)
//set new configuration from file for this request
//cache the configuration for future use in a new thread
//else
//set configuration from cache for this request
return super.onRequest(request, actionMethod);
}
}
Looking up the URL and getting/setting the cache is easy, but I cannot figure out how to SET a new configuration programmatically for Play Framework 2.1 and the documentation is a little light on things like this.
Any thoughts? Anyone know a better, more efficient way to do this?
So, in a sort of roundabout way, I created the basis for a multi-tenant Play application using a Scala Global. There may be a more efficient way to implement this using a filter, but I'm finding this seems to work so far. This does not appear to be as easily implemented in Java.
Instead of using the configuration file, I'm using the database. I assume it would be far more efficient to use a key-value cache, but this seems to work for now.
In Global.scala:
object Global extends GlobalSettings {
override def onRouteRequest(request: RequestHeader): Option[Handler] = {
if (request.session.get("site").isEmpty){
val id = models.Site.getSiteIDFromURL(request.host)
request.session.+("site" -> id)
}
super.onRouteRequest(request)
}
}
And then, obviously, you have to create a database model to query the site based on the request domain and/or the session value set in the request. If anyone knows a better way I'd love to hear it.

Cache data for post requests on server startup

I have a large CSV file which needs to be parsed in order to make post requests to a REST API.The post request body is a json string. The first line in the file has keys and following lines are the values, e.g.
FirstName,LastName
John,Doe
Mark,Twain
So the post body will be something like {"FirstName":"John", "LastName":"Doe"}
This file will be used to create test data for the developers. I will provide a simple page where the developers can enter an account number and hit Submit. The goal is to parse this file and make POST requests to a REST API service.
I want to avoid reading the file each time a request comes in but rather cache these requests on startup to avoid the hassle of reading/parsing the file each time, so that each time a request comes in the request body simply needs to be retrieved from a cache . Is caching these POST request on startup the right way to go here ?
Also there might be a need to add more CSV files just to have variety of data.
What would be a way to make this scalable ?
The format(key names) of the CSV file will be same so each file can be parsed in the same way.
It can be implemented in N number of ways based on your requirement , here is a simple example. You can keep a class like
class Contact{
private String firstName;
private String lastName;
}
and in your other class which holds this value
class RestEnterpriseService{
List<Contact> contacts;
#PostConstruct
init(){
contacts = readFromJSON("JSON URL");
}
}
This can be done in several ways.
If you are using an Spring Framework or Java EE container, you can use the PostConstruct style solution as #AvinashSingh said above.
If you are in some Servlet container, you can do startup tasks using Servlet's Listener or other ways.
Also you can implement it your self, there are so many ways you can do that. Like using an guard variable to detect whether your contacts list is cached; or use skills which like Singleton Design Pattern.

Spring MVC Request mapping, can this be dynamic/configurable?

With Spring MVC, I know how you set the RequestMapping in every controller and method/action.
But what if I wanted this to be configurable, so for example I the following controllers:
BlogController
- with methods for listing blogs entries, single entry, new, update, etc.
ArticleController
- with methods for listing articles entries, single entry, new, update, etc.
Now in my application, the administrator can setup 2 blogs for the webiste, and 1 article section so the urls would be like:
www.example.com/article_section1/ - uses ArticleController
www.example.com/blog1/ - uses BlogController
www.example.com/blog2/ - uses BlogController
Maybe after a while the administrator wants another article section, so they just configure that with a new section like:
www.example.com/article_section2/
This has to work dynamically/on-the-fly without having to restart the application of course.
My question is only concerned with how I will handle url mappings to my controllers.
How would this be possible with Spring MVC?
I only know how to map urls to controllers using #RequestMapping("/helloWorld") at the controller or method level, but this makes the url mappings fixed and not configurable like how I want it.
Update:
I will be storing the paths in the database, and with the mapping to the type of controller so like:
path controller
/article_section1/ article
/blog1/ blog
/blog2/ blog
..
With the above information, how could I dispatch the request to the correct controller?
Again, not looking to reload/redeploy, and I realize this will require more work but its in the spec :)
Would this sort of URL mapping work for you?
www.example.com/blog/1/
www.example.com/blog/2/
If yes, then that's easy: Spring 3 supports path variables: http://static.springsource.org/spring/docs/3.0.x/reference/mvc.html#mvc-ann-requestmapping-advanced
Alternatively, you can create a generic request mapping and your own sub-dispatcher that reads a config file, but I think that's probably more work than it's worth.
Truly changing the request mappings at runtime might be hard (and not really recommended, since small errors can easily occur). If you still wish to do it, perhaps JRebel, and more specificly LiveRebel can be interesting for live redeployment of code and configuration.
Otherwise, like other posts suggested, RequestMappings supports wildcards, the limits of this should be clear after a quick read of the official documentation.
Try using with #RequestMapping wild cards as below:
#RequestMapping(value="/article_section*/"}
public void getArticle(....){
//TODO implementation
}
#RequestMapping(value="/blog*/"}
public void getBlog(....){
//TODO implementation
}
Hope this helps!!!
Also another solution might be to create a custom annotation that holds the already defined path on the #RequestMapping and also the new one to apply, let's say #ApiRestController.
Then, before the Spring context loads, the #Controller classes can be changed to have their annotation values changed at runtime by the new one (with the desired path). By doing this, Spring will load the enhanced request mapping and not the default one.
Created a small project to exemplify this for someone that needs this in the future https://gitlab.com/jdiasamaro/spring-api-rest-controllers.
Hope it helps.
Cheers.
doesn't this work?
#RequestMapping("/helloWorld*")

Categories

Resources