How to dynamically change connection string with each API Call - asp.net-web-api

I'm new to working with APIs, but from what I understand I have created a service folder with 2 classes called DataRepository and IDataRepository. The DataRepository class interacts with the DataContext class. However my Connection string is not in the DataContext class, but in the Startup class. The reason that I'd like to be able to dynamically change the connection string is because, I have many instances of the same database. Each one represent the data of a different. Now the issue is how can I set the connection string dynamically through each webapi call? I plan on getting the connection string parameter with each call.

are you using authorization tokens? if so, you can put your connection string as part of the claims. i suggest to not put the whole connection string in the parameter. if you want an easier approach, you can have a string parameter that can tell if what type of db it should go to,
ex.
public async Task<IHttpActionResult> youApi(string type){
//then you can have a switch statement to know what database it will go to
string connectionString= "";
switch(type)
case "database1":
connectionString = "datasrc=database1";
//and so on
}
im not sure if this is the best approach. i hope this helps.

Related

spring+jaxws: is there a better way than static variables to keep global status?

I have a webservice (cxf) which creates a new Thread each time a time-consuming method is invoked, returning an ID to the client, passed as a token to another web method to check that specific thread's execution state:
public String doWork(){
String id = /***randomnly generates an ID****/
executor.execute(**some runnable**);
// need to save the guy above
return id;
}
public String checkStatus(String id){
/* Here I would basically access to an hashmap
of tasks, pick the one identified by that ID
and check its state */
}
My problem, as you can see above, is to keep a reference to the task(s) so that I can track its execution. Idea I came up with is the following:
#Webservice
public class MyService{
private static HashMap<String, Future> futures = new HashMap<String,Future>();
But is there some better way?Moreover what could be the possible drawbacks of this choice?
Another alternative for storing global state is using a database. Not knowing all the details of your application, the only thing that comes to mind is that depending on how they're used static variables can have issues with thread safety.
It helps to know a few things about the underlying programming model of Java EE servlets, upon which JAX-WS and such are built. This answer explains things well.
To retain information associated with a client for the duration of a session, you can obtain the session in the body of your method and store information in it:
Message message = PhaseInterceptorChain.getCurrentMessage();
HttpServletRequest request = (HttpServletRequest)message.get(AbstractHTTPDestination.HTTP_REQUEST);
HttpSession session = request.getSession(true);
session.setAttribute("id", id);
Upon subsequent method invocations you can retrieve session data in the same manner.
A really basic (ancient) tutorial: Maintaining Client State.

how to share the token between classes

I have having a design issue with asp.net web-api and would like to know how to solve this problem
public abstract class BaseApiController<TEntity> : ApiController where TEntity : Entity
{
protected string GetUsername()
{
return Utilities.GetUsername(Request.Headers.Authorization);
}
//some other code
}
public class StakeholderApiController : BaseApiController<Stakeholders>
{
ILogger _logger = new CustomApiLogger("StkhManager", GetUsername())
//some other code
}
now the problem I have is:
I have the BaseApiController which I am using the share certain functionality between all ApiControllers.
And then I have some specified ApiController for certain not shared functionality.
Now while doing logging, I do want to log the logged in user's name, the problem is I have to pass it everytime I create a new instance, is there a way I can make the logged in user's name global for the current api request so that it can be accessed everywhere.
I cannot make it static, otherwise for others request it will give wrong username.
is there a way I can avoid passing it everytime. Given that webapi is stateless, so session cant be used, is there anyother way??
I am using angularjs front end, hence I am NOT using any authorization technique provided by MVC/.net
Note:
I cannot move creation of Logger to base class for certain reasons
This is just one example, I want to use the logged in user's name in many other place. Hence dont want to pass it around.
There is a standard pattern in setting and accessing principal with ASP.NET Web API. From an ApiController such as your BaseApiController, you can just use the User property to retrieve the same. To set it, typically, the HttpRequestContext is obtained from the request object and the principal is set like so.
Request.GetRequestContext().Principal = new ClaimsPrincipal(...);
BTW, you can access the current request object in the Web API pipeline pretty much from anywhere.

ArgumentResolvers within single transaction?

I am wondering if there is a way to wrap all argument resolvers like for #PathVariables or #ModelAttributes into one single transaction? We are already using the OEMIV filter but spring/hibernate is spawning too many transactions (one per select if they are not wrapped within a service class which is be the case in pathvariable resolvers for example).
While the system is still pretty fast I think this is not necessary and neither consistent with the rest of the architecture.
Let me explain:
Let's assume that I have a request mapping including two entities and the conversion is based on a StringToEntityConverter
The actual URL would be like this if we support GET: http://localhost/app/link/User_231/Item_324
#RequestMapping("/link/{user}/{item}", method="POST")
public String linkUserAndItem(#PathVariable("user") User user, #PathVariable("item") Item item) {
userService.addItem(user, item);
return "linked";
}
#Converter
// simplified
public Object convert(String classAndId) {
return entityManager.find(getClass(classAndId), getId(classAndId));
}
The UserService.addItem() method is transactional so there is no issue here.
BUT:
The entity converter is resolving the User and the Item against the database before the call to the Controller, thus creating two selects, each running in it's own transaction. Then we have #ModelAttribute methods which might also issue some selects again and each will spawn a transaction.
And this is what I would like to change. I would like to create ONE readonly Transaction
I was not able to find any way to intercept/listen/etc... by the means of Spring.
First I wanted to override the RequestMappingHandlerAdapter but the resolver calls are well "hidden" inside the invokeHandleMethod method...
The ModelFactory is not a spring bean, so i cannot write an interceptor either.
So currently I only see a way by completely replacing the RequestMappingHandlerAdapter, but I would really like to avoid that.
And ideas?
This seems like a design failure to me. OEMIV is usually a sign that you're doing it wrong™.
Instead, do:
#RequestMapping("/link/User_{userId}/Item_{itemId}", method="POST")
public String linkUserAndItem(#PathVariable("userId") Long userId,
#PathVariable("itemId") Long itemId) {
userService.addItem(userId, itemId);
return "linked";
}
Where your service layer takes care of fetching and manipulating the entities. This logic doesn't belong in the controller.

Storing session data in controller

I'm new to Spring. I'm working on a MVC application that would works as follows:
1) user fills the form with data necessary to create the connection to some service
2) controller gets the data from input, create new object serviceManager and save this object e.g in some HashMap with serviceId
3) next time user wants to use this service, controller using serviceId reads data from HashMap.
So I simply need to store this HashMap throughout the whole session in my controller for future use. What would be the best way to accomplish that? Maybe creating serviceManager object each time and reading data from database is the proper solution? In my controller I'm already using #Autowired fields which perfectly serve the purpose, but they're defined in spring xml and I have to store the data dynamically.
Seems your requirement is kind of same with mine which I should keep the main data in the session and every time get the detail data from client and combine 2 kind of data to retrieve something from database. I just put the main part data in the session and then in the whole session that I can get it. I also try to use #SessionAttribute, but after tried dozens of time, I gave it up, it has a lots of problems. So if you can, I just recomment you to store the data in session, that's the samplest way.
I'm newish to spring myself, but as far as putting this in the session:
#Controller
#SessionAttributes({"myObject"})
public class MyController() {
...
#RequestMapping(value="/foo")
// Corrected as per Costi below
// public String someMethod(#PathVariable MyObject myObject) {
public String someMethod(#ModelAttribute MyObject myObject) {
...
}
}
#SessionAttributes will put a MyObject named myObject into the session, if it's not already there, and the #PathVariable pulls it down so you can use it in the method.
The curlys in session attributes aren't necessary for just one attribute, however, you can specify more than one, comma separated, when you use the array notation (which is to say: the curlys)

Factory pattern:Passing arguments to concrete class

I have two classes coded to a single interface IStore with one method StoreData(data) - one class sends data to a web service that writes to a DB, the other writes data directly to the DB. (factory pattern)
public IStore GetStorageClass(StorageType type)
{
if (type == StorageType.WebService)
return new WebService();
else
return new DatabaseStore();
}
Now, the DatabaseStore class needs a connection string to work.
The question is, whose responsibility is it to provide the connection string to the DatabaseStore and how? I thought of:
The factory just knows the connection string to pass to DatabaseStore
The DatabaseStore constructor reads it from config which the end user has provided.
The caller of GetStorageClass, though not aware of the exact implementation, passes a Dictionary of parameters and values where the parameter is connection string (caller knows working with databases needs connection strings)
Which option should I choose and am I using the Factory pattern correctly here?
Appreciate the help!
The responsibility is to the class containing GetStorageClass. Either it was constructed with a connection string value provided to it's constructor or it has a private method which reads the value from another source.
Passing in a key-value store in addition to the StorageType is going to be too ambigious, the consumer of the API only wants to get an instance of IStore, not configure it as well.
If you need to do configuration for particular IStore implementations you may want to implement the Builder pattern for that implementation and inject the builder into the factory.

Resources