Friends tell me what is the core meaning of init parameter in case of a servlet.
I know that how to initialize it in a web.xml but I don't know what is the actual purpose of it why it is required? Please tell me with a good example.
The Javadoc says: "A convenience method which can be overridden so that there's no need to call super.init(config)."
The init method's main purpose is to allow customization while you are initializing the servlet.
The simplest implementation is when you don't want to do any customization according to your application you can always call super.init method.
To understand meaning of what different init params can be there and how init method is useful:
Imagine a system Of BookManagement system, here for adding books and removing books from db you will be needing Database connection over which you can access the data. Now as Servlet's init method is called for the first request and database connection also needs be created only once(or n number of time if doing connection pooling) then initializing the database connection is something that you should do in init method.
A code snippet from Softlab example , let's assume that getInitParameter method reads the databaseUrl and other properties from web.xml
public class DBServlet ... {
Connection connection = null;
public void init() throws ServletException {
// Open a database connection to prepare for requests
try {
databaseUrl = getInitParameter("databaseUrl");
... // get user and password parameters the same way
connection = DriverManager.getConnection(databaseUrl,
user, password);
} catch(Exception e) {
throw new UnavailableException (this,
"Could not open a connection to the database");
}
}
...
}
One more example of counting the number of time servlet was accessed: https://docstore.mik.ua/orelly/java-ent/servlet/ch03_03.htm
So in Summary: To do customization like read the initial values of variable or to initialize resources(like db connection) you can use init method.
Below is the source code of init methods :
public void init(ServletConfig config)throws ServletException
{
this.config = config;
int();
}
public void init() throws ServletException;
It is recommended to override to init() method, not init(ServletConfig).
When overriding init(ServletConfig), the first thing that must be done is to call:
super.init(config);
If you do this then calling directly to getServletContext() in your method will no longer result in an NPE.
Related
I am moving an asp.net mvc5 application using EF6 to asp.net core MVC 3.0 using EF Core.
In my mvc5 application I have some administrative operation that modify the database and take a long time, so I use a pattern when I create a new DBContext that is not the one that is associated with the request context and then run the task in the background using Task.Run. This has been working fine for years.
In converting to .net core it was unclear how to create a new DBContext in the way that I was doing it in my old codebase. It seems like I should be able to create a Transient DBContext in these cases and all should be fine.
So I created a subclass of MyDbContext called MyTransientDbContex and in my Configure class I added this service:
services.AddDbContext<MyTransientDbContex>(options =>
options.UseSqlServer(
context.Configuration.GetConnectionString("MyContextConnection")),
ServiceLifetime.Transient, ServiceLifetime.Transient);
In my controller I inject the context in the action that needs the transient service and spawn a thread to do something with it:
public ActionResult Update([FromServices] MyTransientContext context) {
Task.Run(() =>
{
try {
// Do some long running operation with context
}
Catch (Exception e) {
// Report Exception
}
finally {
context.Dispose();
}
}
return RedirectToAction("Status");
}
I would not expect my transient context to be disposed until the finally block. But I am getting this exception when attempting to access the context on the background thread:
Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Object name: 'MyTransientContext'.'
And indeed the _disposed flag is set to true on the context object.
I put a breakpoint on the constructer for MyTransientContext and "Made an Object ID" of the this pointer so that I could track the object. This transient object is being created and is the same one that is inject into my controller action. It's also the same object that I'm trying to reference when the exception is thrown.
I tried setting a data breakpoint on the _disposed member in order to get a callstack on when disposed is being set to true, but the breakpoint won't bind.
I also tried overriding the Dispose method on MyTransientContext, and it isn't called until my explicit dispose in the finally block, which is after the exception is thrown and caught.
I feel like I'm missing something fundamental here. Isn't this what the transient services are for? What would dispose a Transient service?
One last detail - MyTransientContext is derived from MyContext, which is in turn derived from IdentityDbContext (Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityDbContex)
Edit: The reason that I went down the path of using a Transient was because of this ef core document page: https://learn.microsoft.com/en-us/ef/core/miscellaneous/configuring-dbcontext. It states that "...any code that explicitly executes multiple threads in parallel should ensure that DbContext instances aren't ever accessed concurrently. Using dependency injection, this can be achieved by either registering the context as scoped and creating scopes (using IServiceScopeFactory) for each thread, or by registering the DbContext as transient (using the overload of AddDbContext which takes a ServiceLifetime parameter)."
As xabikos pointed out, this seems to be overriden by the scoping of the asp.net DI system, where it looks like anything created by that system is scoped to the request context, including Transient objects. Can someone point out where that's documented so that I can better understand how to work with the limitations?
f you want manage the lifetime of service, you can instantiate it manually (or use a factory) :
public ActionResult Update()
{
Task.Run(() =>
{
using(var context = new MyTransientContext(...))
{
try
{
// Do some long running operation with context
}
catch (Exception e)
{
// Report Exception
}
}
}
return RedirectToAction("Status");
}
Or you can use IServiceProvider to get and manage a service :
public class MyController
{
private IServiceProvider _services;
public MyController(IServiceProvider services)
{
_services = services;
}
public ActionResult Update()
{
var context = (MyTransientContext)_services.GetService(typeof(MyTransientContext));
Task.Run(() =>
{
using (context)
{
try
{
// Do some long running operation with context
}
catch (Exception e)
{
// Report Exception
}
}
}
return RedirectToAction("Status");
}
}
You mixed the concepts of transient objects that are created by internal DI container asp.net core provides.
You configure the MyTransientContext to be transient in the internal DI system. This practically means that every time a scope is created then a new instance is returned. For asp.net application this scope matches an HTTP request. When the requests ends then all the objects are disposed if applicable.
Now in your code, that is a synchronous action method you spawn a Task with Task.Run. This is an async operation and you don't await for this. Practically during execution this will be started but not wait to finish, the redirect will happen and the request will end. At this point if you try to use the injected instance you will get the exception.
If you would like to solve this you need change to an async action and await on the Task.Run. And most likely you don't need to spawn a new Task. But you need to understand that this is not probably the best way as it will need for the long operation to finish before the redirect takes place.
An alternative to this would be to use a messaging mechanism, and send a message that triggers this operation. And you have another component, like worker service that listens for those messages and process them.
I'm quite new to the Microservice world and particularly vertX. I want my verticle to start anyway even there is no database connection available (e.g. database URL missing in configuration). I already managed to do this and my verticle is starting.
The issue now is that I want my verticle to notice when the database connection is available again and connect to it. How can I do this ?
I thought about creating another Verticle "DatabaseVerticle.java" which would send the current DB config on the event bus and my initial verticle would consume this message and check whether the config info is consistent (reply with success) or still missing some data (reply with fail and make the DatabaseVerticle check again).
This might work (and might not) but does not seem to be the optimal solution for me.
I'd be very glad if someone could suggest a better solution. Thank you !
For your use case, I'd recommend to use the vertx-config. In particular, have a look at the Listening to configuration changes section of the Vert.x Config documentation.
You could create a config retriever and set a handler for changes:
ConfigRetrieverOptions options = new ConfigRetrieverOptions()
.setScanPeriod(2000)
.addStore(myConfigStore);
ConfigRetriever retriever = ConfigRetriever.create(vertx, options);
retriever.getConfig(json -> {
// If DB config available, start the DB client
// Otherwise set a "dbStarted" variable to false
});
retriever.listen(change -> {
// If "dbStarted" is still set to false
// Check the config and start the DB client if possible
// Set "dbStarted" to true when done
});
The ideal way would be some other service telling your service about database connection. Either through event bus or HTTP, what you can do is when someone tries to access your database when connection is not made just try to make some DB call and handle the exception, return a boolean as false. Now when you get a message on event bus, consume it and save it in some config pojo. Now when someone tries to access your database, look for config and if available make a connection.
Your consumer:
public void start(){
EventBus eb = vertx.eventBus();
eb.consumer("database", message -> {
config.setConfig(message.body());
});
}
Your db client(Mongo for this eg):
public class MongoService{
private MongoClient client;
public boolean isAvailable = false;
MongoService(Vertx vertx){
if(config().getString("connection")){
client = MongoClient.createShared(vertx, config().getString("connection"));
isAvailable = true;
}
}
}
Not everything in Vertx should be solved by another verticle.
In this case, you can use .periodic()
http://vertx.io/docs/vertx-core/java/#_don_t_call_us_we_ll_call_you
I assume you have some function that checks the DB for the first time.
Let's call it checkDB()
class PeriodicVerticle extends AbstractVerticle {
private Long timerId;
#Override
public void start() {
System.out.println("Started");
// Should be called each time DB goes offline
final Long timerId = this.vertx.setPeriodic(1000, (l) -> {
final boolean result = checkDB();
// Set some variable telling verticle that DB is back online
if (result) {
cancelTimer();
}
});
setTimerId(timerId);
}
private void cancelTimer() {
System.out.println("Cancelling");
getVertx().cancelTimer(this.timerId);
}
private void setTimerId(final Long timerId) {
this.timerId = timerId;
}
}
Here I play a bit with timerId, since we cannot pass it to cancelTimer() right away. But otherwise, it's quite simple.
Can I able to access appSettings section in my ASP.NET web.config file from a method in another referenced Class Library project when it is called as a new Thread?
I'm accessing the setting through a property as
private static string TempXmlFolder
{
get
{
return System.Web.HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["ReceiptTempPath"] ?? "~/Receipts/TempXML");
}
}
There is an extension method for the matter to generate the receipt.
internal static void GenerateReceipt(this IMatter matter)
{
try
{
string XmlFile = TempXmlFolder + "/Rec_" + matter.MatterID + ".xml";
// ...
// Generating receipt from the matter contents
// ...
// Saving generated receipt
}
catch (Exception ex)
{
ex.WriteLog();
}
}
I'm calling the receipt generation as a new thread from the class library like
Thread printThread = new Thread(new ThreadStart(this.GenerateReceipt));
// To avoid exception 'The calling thread must be STA, because many UI components require this' (Using WPF controls in receipt generation function)
printThread.SetApartmentState(ApartmentState.STA);
printThread.Start();
// ...
// Do another stuffs
// ...
// Wait to generate receipt to complete
printThread.Join();
But since the HttpContext.Current is null inside the Thread, I'm not able to access the current web server configuration file.
Can you suggest there any way other than passing the current HttpContext to the Thread? If no, what are the things I've to take care to keep thread safety?
Edit #1
Currently I'm passing the HttpContext to the thread like
System.Web.HttpContext currentContext = System.Web.HttpContext.Current;
Thread printThread = new Thread(() => this.GenerateReceipt(currentContext));
and in the function,
internal static void GenerateReceipt(this IMatter matter, System.Web.HttpContext htCont)
{
string TempXmlFolder = htCont.Server.MapPath(ConfigurationManager.AppSettings["ReceiptTempPath"] ?? "~/Receipts/TempXML");
//...
Pass the TempXmlFolder into the thread. Don't rely on HttpContext.Current. Alternatively, pass the value of HttpContext.Current to the thread and calculate the value of TempXmlFolder later.
You can pass the value using any way you want. Maybe a field or a local variable that you capture with a lambda.
Is there any way in ASP.NET Web API to mark an exception as handled in an ExceptionFilterAttribute?
I want to handle the exception at the method level with an exception filter and stop the propagation to a globally registered exception filter.
Filter used on a controller action:
public class MethodExceptionFilterAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
if (context.Exception is NotImplementedException)
{
context.Response = new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent(context.Exception.Message)
};
// here in MVC you could set context.ExceptionHandled = true;
}
}
}
The globally registered filter:
public class GlobalExceptionFilterAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
if (context.Exception is SomeOtherException)
{
context.Response = new HttpResponseMessage(HttpStatusCode.SomethingElse)
{
Content = new StringContent(context.Exception.Message)
};
}
}
}
Try throwing an HttpResponseException at the end of your local handling. By design, they are not caught by exception filters.
throw new HttpResponseException(context.Response);
Web API 2 is designed with inversion of control in mind. You consider the possibility for the exception to already be handled, rather than interrupting the filter execution after you handle it.
In this sense, attributes deriving from ExceptionFilterAttribute should check if the exception is already handled, which your code already does since is operator returns false for null values. In addition, after you handle the exception, you set context.Exception to null in order to avoid further handling.
To achieve this in your code, you need to replace your comment from MethodExceptionFilterAttribute with context.Exception = null to clear the exception.
It is important to note that it is not a good idea to register more than one global exception filter, due to ordering issues. For information about the execution order of attribute filters in Web API, see the following thread Order of execution with multiple filters in web api.
I have the following configured within my IContainer Initialize routine:
x.For<IDbConnection>().Use<SqlConnection>().Ctor<string>().Is(MY_SQL_CONNECTION_STRING);
Here's the constructor for my service:
private readonly IForumRepository _repo;
public ForumService(IForumRepository repo)
{
_repo = repo;
}
And here's the constructor for my repository:
private readonly IDbConnection _cn;
public ForumRepository(IDbConnection connection)
{
_cn = connection;
}
In one of my service routines, I am calling a method to get an object in my repository, then upon returning to the service layer I call a 2nd method in my repository - however, on this second call to the repository, my connection (_cn) no longer has a connection string associated with it (it appears to be wiped upon exiting the using {} block the first time my service called a method in the repository.
Here's the first method that I call in the repository.
public Tag GetTag(int id)
{
Tag o;
const string q = #"select * from tags where id = #pId";
using (_cn)
{
_cn.Open();
o = _cn.Query<Tag>(q, new { pId = id }).SingleOrDefault();
} *** AT THIS POINT THE CONN STRING PROPERTY OF _CN IS CLEARED?!
return o;
}
I 'd have thought this should work fine seeing as the constructor for my service instantiates a SQL Connection which the first call to the repo utilizes fine, and seeing as subsequent calls to my repo are in the same service scope I'd have thought that repository's SqlConnection dependency should still retain the original connection string details.
Can someone please shed some light on where I'm going wrong with this?
After the using block is finished, the object being used will be disposed. Does the connection string get removed on disposal? In any case, you likely shouldn't use the object after is has been disposed.
Based on the code in your post, I would think you don't want to use the using block? I think you will want to manually close the connection, though (I think using will do that automatically as part of disposal).