Java - Spring MVC - Redirect to route without button/change url dynamically - multithreading

Please excuse me for my bad english.
This is my problem using Spring MVC:
Let assume that a user is clicking on a button and arrived to a route called "/randomRoute".
I want him to have the possibility to keep doing his job (for example filling a form). About a certain amount of time (represented by the Thread.sleep in the thread), and whatever he did before, I want him to be redirected to a new route called "/newRandomRoute".
I thought about using Thread.run so that the user can continue his work until the delay is done but I don't know how to implement the redirect to the new route.
Is that possible with Spring? Or is there a way to change the url after the Thread.sleep method?
If you want more precision (I am trying to do something on the "Go to "newRandomRoute" page" comment:
#Controller
#RequestMapping("/home")
public class Chat {
#GetMapping("/randomRoute")
public String displayRandomRoute() {
new Thread() {
#Override
public void run() {
try {
Thread.sleep(5000);
// Go to "/newRandomRoute" newPage
} catch (Exception e) {}
}
}.start();
return "page";
}
#GetMapping("/newRandomRoute")
public String displayNewRandomRoute() {
return "newPage";
}
}
Thanks for your help :)

Related

Liferay : How can I land to custom url on signout

I'm not sure if I can achieve this by simply configuration or I need to override LogoutAction for it.
I've configured multiple organisation and each organisation has there own site which I want to navigate to my custom url for different site instead of default url on logout from liferay.
[EDITED]
I want to navigate on different url for each site, not a common url.
Thanks
For this you can use default.logout.page.path property (in portal-ext.properties file)
default.logout.page.path=
#default.logout.page.path=/web/guest/logout
I think you can achieve this by overriding LogoutPostAction through a hook.
Define your LogoutPostAction class in portal.properties of your hook:
logout.events.post=com.my.action.MyLogoutPostAction
Here is a sample code for the class to redirect to your desired page:
public class MyLogoutPostAction extends Action {
#Override
public void run(HttpServletRequest request, HttpServletResponse response)
throws ActionException {
try {
doRun(request, response);
}
catch (Exception e) {
throw new ActionException(e);
}
}
protected void doRun(HttpServletRequest request, HttpServletResponse response)
throws Exception {
long groupId = PortalUtil.getScopeGroupId(httpReq);
// code to fetch the Group
// ....
// ....
//
String postLogoutURL = "create your own URL";
// if required: add a parameter
postLogoutURL = HttpUtil.setParameter(postLogoutURL, "my_param", "my_param_value");
// redirect to that URL
response.sendRedirect(postLogoutURL);
}
}
The only thing that can be a road block with this approach would be if Liferay has lost context of the current group from which the user was logged-out. I have not tested the code.

Is it possible to exclude a url from Application Insights?

We have an Azure web role deployed that has been using Application Insights (ver. 1.0.0.4220), however, we're going over our data quota. Is it possible to configure Application Insights ignore a specific URL?
We have a status web service that gets a huge amount of traffic but never throws any errors. If I could exclude this one service URL I could cut my data usage in half.
Out of the box it is not supported. Sampling feature is coming but that would not be configurable by specific url. You can implement your own channel that would have your custom filtering. Basically your channel will get event to be sent, you check if you want to send it or not and then if yes pass to standard AI channel. Here you can read more about custom channels.
There are two things that changed since this blog post has been written:
channel should implement only ITelemetryChannel interface (ISupportConfiguration was removed)
and instead of PersistenceChannel you should use Microsoft.ApplicationInsights.Extensibility.Web.TelemetryChannel
UPDATE: Latest version has filtering support: https://azure.microsoft.com/en-us/blog/request-filtering-in-application-insights-with-telemetry-processor/
My team had a similiar situation where we needed to filter out urls that were successful image requests (we had a lot of these which made us hit the 30k datapoints/min limit).
We ended up using a modified version of the class in Sergey Kanzhelevs blog post to filter these out.
We created a RequestFilterChannel class which is an instance of ServerTelemetryChannel and extended the Send method. In this method we test each telemetry item to be sent to see if it is an image request and if so, we prevent it from being sent.
public class RequestFilterChannel : ITelemetryChannel, ITelemetryModule
{
private ServerTelemetryChannel channel;
public RequestFilterChannel()
{
this.channel = new ServerTelemetryChannel();
}
public void Initialize(TelemetryConfiguration configuration)
{
this.channel.Initialize(configuration);
}
public void Send(ITelemetry item)
{
if (item is RequestTelemetry)
{
var requestTelemetry = (RequestTelemetry) item;
if (requestTelemetry.Success && isImageRequest((RequestTelemetry) item))
{
// do nothing
}
else
{
this.channel.Send(item);
}
}
else
{
this.channel.Send(item);
}
}
public bool? DeveloperMode
{
get { return this.channel.DeveloperMode; }
set { this.channel.DeveloperMode = value; }
}
public string EndpointAddress
{
get { return this.channel.EndpointAddress; }
set { this.channel.EndpointAddress = value; }
}
public void Flush()
{
this.channel.Flush();
}
public void Dispose()
{
this.channel.Dispose();
}
private bool IsImageRequest(RequestTelemetry request)
{
if (request.Url.AbsolutePath.StartsWith("/image.axd"))
{
return true;
}
return false;
}
}
Once the class has been created you need to add it to your ApplicationInsights.config file.
Replace this line:
<TelemetryChannel Type="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.ServerTelemetryChannel, Microsoft.AI.ServerTelemetryChannel"/>
with a link to your class:
<TelemetryChannel Type="XXX.RequestFilterChannel, XXX" />
Alternatively, you can disable the automated request collection and keep only exception auto-collection, just remove the RequestTrackingModule line from applicationinsights.config.
If you still need to collect some of the requests, not just filter all out, you can then call TrackRequest() (in the object of TelemetryClient class) from your code in the appropriate place after you know that you certainly need to log this request to AI.
Update: Filtering feature has been released some time ago and allows for exclusion of certain telemetry items way easier.

c# MVC Site Map - very slow when using roles - very slow

I've installed MVC Site Map Provider for MVC5 and just used everything out of the the box. It works fine. Now I want to implement roles based menu trimming so assuming my controller:
public class Home: Controller
{
[Authorize(Roles="Admin")]
public ActionResult Index()
{
return View();
}
}
Now basically only Admin role users can see the menu. Perfect works fine.
Also to implement this I added to my web.config this line:
<add key="MvcSiteMapProvider_SecurityTrimmingEnabled" value="true" />
The problem is that it works but it's slow. It takes about 7 seconds for the page to load. If I remove the web.config line, basically removing menu trimming based on roles it takes ~300ms for the page to load. Something is wrong in here.
Any ideas why my menu trimming based on roles is slow? I haven't done any customizations.
The security trimming feature relies on creating a controller instance for every node in order to determine if the current user context has access.
The most likely cause of this slowness is that your controllers (or their base class) have too much heavy processing happening in the constructor.
public class HomeController
{
public HomeController() {
// Lots of heavy processing
System.Threading.Thread.Sleep(300);
};
}
The above example will add 300 ms to the page load time for every node that represents an action method in the HomeController. If your other controllers also have heavy processing during instantiation, they will also add additional time to each page load.
When following DI best practices, this is not an issue because heavy processing takes place in external services after the controller instance is created.
public interface IHeavyProcessingService
{
IProcessingResult DoSomethingExpensive();
}
public class HeavyProcessingService : IHeavyProcessingService
{
public HeavyProcessingService() {
}
public IProcessingResult DoSomethingExpensive() {
// Lots of heavy processing
System.Threading.Thread.Sleep(300);
}
}
public class HomeController
{
private readonly IHeavyProcessingService heavyProcessingService;
// The constructor does no heavy processing. It is deferred until after
// the instance is created by HeavyProcessingService.
// The only thing happening here is assignment of dependencies.
public HomeController(IHeavyProcessingService heavyProcessingService) {
if (heavyProcessingService == null)
throw new ArgumentNullException("heavyProcessingService");
this.heavyProcessingService = heavyProcessingService;
};
public ActionResult Index()
{
var result = this.heavyProcessingService.DoSomethingExpensive();
// Do something with the result of the heavy processing
return View();
}
public ActionResult About()
{
return View();
}
public ActionResult Contact()
{
return View();
}
}
Notice in the above example that no heavy processing happens in the constructor? This means that creating an instance of HomeController is very cheap. It also means that action methods that don't require the heavy processing to happen (as in About() and Contact() in the example) won't take the hit of heavy processing required by Index().
If not using DI, MVC still requires that a new controller instance be created for each request (controller instances are never shared between users or action methods). Although, in that case it is not as noticeable on a per user basis because only 1 instance is created per user. Basically, MvcSiteMapProvider is slowing down because of a pre-existing issue with your application (which you can now fix).
Even if you are not using DI, it is still a best practice to defer heavy processing until after the controller instance is created.
public class HomeController
{
private readonly IHeavyProcessingService heavyProcessingService;
public HomeController() {
this.heavyProcessingService = new HeavyProcessingService();
};
public ActionResult Index()
{
var result = this.heavyProcessingService.DoSomethingExpensive();
// Do something with the result of the heavy processing
return View();
}
}
But if moving heavy processing into external services in your application is not an option, you can still defer processing until its needed by moving the processing into another method so it is not too expensive to create controller instances.
public class HomeController
{
public HomeController() {
};
private IProcessingResult DoSomethingExpensive() {
// Lots of heavy processing
System.Threading.Thread.Sleep(300);
}
public ActionResult Index()
{
var result = this.DoSomethingExpensive();
// Do something with the result of the heavy processing
return View();
}
}
Although there is a bug posted for Route values not preserved correctly in v4?
But looks like it was fixed in version 4 next release.
Another Workaround to fix this problem is cache here is a related article.
MVC siteMap provider cache

Allow only one user to access a page at a time in struts application

Having an huge customers profile page if two or more users start using same page and start editing big change will happen in my database so planing to implement Threads concept where only one user can use that customer page
i'm aware about threads concept but confused how to implement it
hope i need to use Singleton class as well
Any suggestion or Logic's will be helpful
I'm using Struts,Hibernate frame work
You may use application context to store a flag variable. Action will use its value to allow only one simultaneous execution.
public class TestAction extends ActionSupport implements ApplicationAware {
private static final String APP_BUSY_KEY = "APP_BUSY";
Map<String, Object> map;
#Override
public void setApplication(Map<String, Object> map) {
this.map = map;
}
#Override
public String execute() throws Exception {
if (map.containsKey(APP_BUSY_KEY)) {
return ERROR;
} else {
map.put(APP_BUSY_KEY, "1");
try {
// action logic here
} finally {
map.remove(APP_BUSY_KEY);
}
return SUCCESS;
}
}
}
If you plan to implement similar logic for two requests (lock after displaying values and release lock after submitting new values) then logic will be more complex and you will also need to handle lock release after timeout.

Codenameone Webbrowser issue

I am trying to display a webpage from codenameone application. It works fine in Iphone but not in andriod mobile.
public void showLoginForm()
{
final Form loginForm = new Form("Login");
loginForm.setUIID("Form1");
loginForm.setLayout(new BorderLayout());
loginForm.setScrollable(false);
try
{
WebBrowser browser = new WebBrowser()
{
//Overrides onStart and onLoad methods to load progress bars for page transitions.
};
browser.setURL(appsGlobalSettings.get(URL_KEY));
loginForm.addComponent(BorderLayout.CENTER,browser);
loginForm.show();
}
catch(Exception e)
{
e.printStackTrace();
}
}
Check your URL. I suggest removing the override code and placing Google.com hardcoded as a URL and proceeding from there. Since it doesn't work in the simulator either make sure you are using Java 7 with JavaFX enabled, with that case it should show a browser and should work for a proper web address.
Shai...It took some time to collect device logs.
But even that is intriguing.
I tried in two ways
No overridden methods in WebBrowser class and http://www.google.co.in as URL.
public void showLoginForm()
{
InfiniteProgress inf = new InfiniteProgress();
Dialog progress = inf.showInifiniteBlocking();
final Form loginForm = new Form("Login");
loginForm.setUIID("Form1");
loginForm.setLayout(new BorderLayout());
try
{
//Log.p("Inside showLoginForm method");
WebBrowser browser = new WebBrowser()
{
};
//browser.setURL(appsGlobalSettings.get(URL_KEY));
browser.setURL("http://www.google.co.in");
//Log.p("Set Broswer url");
loginForm.addComponent(BorderLayout.CENTER,browser);
//Log.sendLog();
loginForm.show();
}
catch(Exception e)
{
e.printStackTrace();
//Log.p(e.toString());
}
}
Result - the same blank screen.
Same code with added Log.p and Log.send() statements.
Result - it works fine
Is this due to some race condition?

Resources