We have created a test suite and in order to run it we are using embedded Grizzly Web Server with JerseyTest framework.
We are extending a custom class from JerseyTest and in its constructor we are creating ApplicationDescriptor and then call superclass setupTestEnvironment() which essentially starts embedded grizzly web server.
Few of our test cases are extending this custom class to start grizzly server directly. However, we are not stopping this embedded server anywhere in the code.
The test cases run fine on windows but on Unix they fail with java.net.BindException port 9998 is in use by another process.
It becomes obvious these tests should fail with similar error on windows too if we are not stopping embedded web server in the code. How they are running fine on windows and failing on unix. Has this something to do with how Unix spawns threads or processes?
P.S. We have also tested whether port 9998 is in use by some other process using netstat -a | grep 9998 but no other process using that port could be found.
i had a similar problem and i did fix it by not using the default port if already used. just add following code to your test case:
#Override
protected int getPort(int defaultPort) {
ServerSocket server = null;
int port = -1;
try {
server = new ServerSocket(defaultPort);
port = server.getLocalPort();
} catch (IOException e) {
// ignore
} finally {
if (server != null) {
try {
server.close();
} catch (IOException e) {
// ignore
}
}
}
if ((port != -1) || (defaultPort == 0)) {
return port;
}
return getPort(0);
}
I had the same problem, when I was writing my integration tests. I didn't get to test on a Windows machine, but on my Unix machine I found the problem was that by default the JerseyTest class utilizes #After on it's tearDown method to close the embedded server. Since I had overridden this method to do clean up on my side, I had to call super.tearDown()
#After
public void tearDown() throws Exception{
super.tearDown();
...
}
After doing this, everything worked as expected.
Related
I have a dotnet core console application build to connect to a Sql Service Broker instance to monitor table changes.
The app monitors one table that is updated from an ERP system and then publishes messages to our bus.
It runs fine when running as a console application, or debugging in my IDE.
I am having an issue when using TopShelf to configure it as a windows service.
Here is the entry point:
private static void Main(string[] args)
{
RegisterComponents();
var serviceHost = HostFactory.Run(sc =>
{
sc.Service<ISalesOrderMonitorService>(s =>
{
var sqlListener = _container.ResolveNamed<SqlDependencyEx>(ListenerKey.SalesOrder);
var changeHandler = _container.Resolve<ISalesOrderChangeHandler>();
var listenerConfig = _container.ResolveNamed<ListenerConfiguration>(ListenerKey.SalesOrder);
var logger = _container.Resolve<ILogger<SalesOrder>>();
s.ConstructUsing(f =>
new SalesOrderMonitorService(sqlListener, changeHandler, listenerConfig, logger));
s.WhenStarted(tc => tc.Start());
s.WhenStopped(tc => tc.Stop());
});
});
var exitCode = (int) Convert.ChangeType(serviceHost, serviceHost.GetType());
Environment.ExitCode = exitCode;
}
The "worker" class:
public abstract class ServiceBase<T, TZ> : IService<T>
where T : IChangeHandler
{
protected readonly IChangeHandler ChangeHandler;
protected readonly SqlDependencyEx Listener;
protected readonly ListenerConfiguration ListenerConfiguration;
protected readonly ILogger<TZ> Logger;
protected ServiceBase(SqlDependencyEx listener, IChangeHandler changeHandler,
ListenerConfiguration listenerConfiguration, ILogger<TZ> logger)
{
Logger = logger;
ListenerConfiguration = listenerConfiguration;
Listener = listener;
ChangeHandler = changeHandler;
}
public virtual void Start()
{
try
{
Listener.TableChanged += (o, e) => ChangeHandler.Process(e);
Listener.Start();
Logger.LogDebug(
$"Listening to changes on the {ListenerConfiguration.Table} table in the {ListenerConfiguration.Database} database");
}
catch (Exception e)
{
Logger.LogError(e, e.Message);
throw;
}
}
public virtual void Stop()
{
Listener.Stop();
}
Install through TopShelf is no problem:
c:>{ServiceName}.exe install -username "serviceAccount" -password "superSecret" -servicename "ServiceName" -servicedescription "Description" -displayname "Service DisplayName" --autostart
When I go to start the service - I get this:
This is misleading because the event viewer shows this:
This is happening way faster than 30 seconds. This is definitely related to how I am configuring TopShelf.
As stated - the application works just fine when run "debug" or even as just an exe console.
I got it figured out. Actually both comments from #DotNetPadawan and #Lex Li indirectly got me there.
For starters - enabling the remote debugger clued me in that my appsetting.json was not being read into my IConfiguration. That was really confusing because everything works fine running locally with a debugger or even just starting the exe.
The link Lex Li points out did not provide the answer - however that article had this reference:
Host and Deploy aspnetcore as a Windows Service
It was here that I found this little nugget:
The current working directory returned by calling GetCurrentDirectory for a Windows Service is the C:\WINDOWS\system32 folder. The system32 folder isn't a suitable location to store a service's files (for example, settings files). Use one of the following approaches to maintain and access a service's assets and settings files.
The link explains how to conditionally set the current directory if the app is running as a service.
var isConsole = args.Contains("-mode:console");
if (!isConsole)
{
var pathToExe = Process.GetCurrentProcess().MainModule?.FileName;
var pathToContentRoot = Path.GetDirectoryName(pathToExe);
Directory.SetCurrentDirectory(pathToContentRoot);
}
Putting this out there for anyone else that runs into this problem.
Admittedly - netcore 3.0 is likely the better way to go - but I don't have the bandwidth to upgrade everything is this repo (lots of shared stuff) to 3.0. I needed to get this working.
We need to invoke URL contains the caller number each time there is an inbound call, we are using Grandstream UCM6204 PBX.
There is a function called SendURL() that can be used through Asterisk, I connected to Asterisk using PuTTy but I'm not sure what to do next?
After doing some research, I found that I couldn't have direct access to Asterisk through UCM devices, which will not allow us to modify the dial plan.
Is the only approach by creating a third party application to communicate with AMI and do the job? Problem with this scenario that this application should be online and working 24/7.
I wrote C# code to accomplish this, but it is not working as expected.
public FormMain()
{
InitializeComponent();
AstCon = new ManagerConnection(ConfigurationManager.AppSettings["astHost"],
int.Parse(ConfigurationManager.AppSettings["astPort"]),
ConfigurationManager.AppSettings["astUser"], ConfigurationManager.AppSettings["astPass"]);
AstCon.NewState += astCon_NewState;
AstCon.ConnectionState += astCon_ConnectionState;
try
{
AstCon.Login();
}
catch (Exception ex)
{
MessageBox.Show(
$"Error connecting to {ConfigurationManager.AppSettings["astHost"]}. Error: {ex.Message}");
// Terminate Application
Application.Exit();
}
}
private void astCon_NewState(object sender, NewStateEvent e)
{
if (e.ChannelStateDesc.ToLower() == "ring" && e.Connectedlinenum == "6401")
{
if (ConfigurationManager.AppSettings["ScreenPopPath"] != null)
{
var runString = ConfigurationManager.AppSettings["ScreenPopPath"];
runString = runString.Replace("{callerid-number}", e.CallerId);
Process.Start(runString);
}
}
}
void astCon_ConnectionState(object sender, ConnectionStateEvent e)
{
connectionStateLbl.Text = AstCon.IsConnected() ? $"Connected to: {AstCon.Username}#{AstCon.Hostname}" : $"Disconnected, reconnecting to {AstCon.Hostname}...";
}
}
You can use CURL function. But for invoke it need understand PBX dialplan and hooks
You can use external AMI app.
You can read CEL events in database.
How can I check inside the application if it is being hosted in IIS?
Check if the environment variable APP_POOL_ID is set.
public static bool InsideIIS() =>
System.Environment.GetEnvironmentVariable("APP_POOL_ID") is string;
All of environment variables that iis sets on a child process
I've tried the answer by Branimir Ričko but found that it's not correct: this environment variable is also set when running under IIS express.
So here is my modified version:
static bool IsRunningInsideIIS() =>
System.Environment.GetEnvironmentVariable("ASPNETCORE_HOSTINGSTARTUPASSEMBLIES") is string startupAssemblies &&
startupAssemblies.Contains(typeof(Microsoft.AspNetCore.Server.IISIntegration.IISDefaults).Namespace);
I believe there is no direct way how to achieve that out of the box. At least I haven't found one. And the reason, as I can tell is the fact ASP.NET Core application is actually a self-contained application knowing nothing about it's parent context, unless the later will reveal information about itself.
For example in the configuration file we can tell which type of the installation we're running: production or development. We can assume that production is IIS, while development is not. However that didn't worked for me. Since my production setup could be either IIS or windows service.
So I have worked around this problem by supplying different command line arguments to my application depending on type of run it supposed to perform. That, actually, came naturally for me, since windows service indeed requires different approach to run.
For example in my case code looked somewhat like so:
namespace AspNetCore.Web.App
{
using McMaster.Extensions.CommandLineUtils;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.WindowsServices;
using System;
using System.Diagnostics;
using System.IO;
public class Program
{
#region Public Methods
public static IWebHostBuilder GetHostBuilder(string[] args, int port) =>
WebHost.CreateDefaultBuilder(args)
.UseKestrel()
.UseIISIntegration()
.UseUrls($"http://*:{port}")
.UseStartup<Startup>();
public static void Main(string[] args)
{
var app = new CommandLineApplication();
app.HelpOption();
var optionHosting = app.Option("--hosting <TYPE>", "Type of the hosting used. Valid options: `service` and `console`, `console` is the default one", CommandOptionType.SingleValue);
var optionPort = app.Option("--port <NUMBER>", "Post will be used, `5000` is the default one", CommandOptionType.SingleValue);
app.OnExecute(() =>
{
//
var hosting = optionHosting.HasValue()
? optionHosting.Value()
: "console";
var port = optionPort.HasValue()
? new Func<int>(() =>
{
if (int.TryParse(optionPort.Value(), out var number))
{
// Returning successfully parsed number
return number;
}
// Returning default port number in case of failure
return 5000;
})()
: 5000;
var builder = GetHostBuilder(args, port);
if (Debugger.IsAttached || hosting.ToLowerInvariant() != "service")
{
builder
.UseContentRoot(Directory.GetCurrentDirectory())
.Build()
.Run();
}
else
{
builder
.UseContentRoot(Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName))
.Build()
.RunAsService();
}
});
app.Execute(args);
}
#endregion Public Methods
}
}
This code not only allows select type of the hosting (service and console — the option that IIS supposed to use), but also allows to change port which is important, when you're running as Windows service.
Another good thing is usage of argument parsing library, McMaster.Extensions.CommandLineUtils — it will show information about configured command line switches, so it would be easy to select right values.
There is a project that will involve sftp file transfers to a server. I have tried using ftp protocol and chose winscp.exe - sftp as my program to record. There were events being recorded however there is nothing generated after I finished recording.
If ftp protocol is not the answer to sftp file transfers can anybody give me some insight or tips on how I can do loadtests using LR on sftp file transfers?
I am using Loadrunner 11 for this.
Thanks in advance.
LoadRunner FTP Protocol doesn't support SFTP. It only supports FTP and FTPS (FTP over SSL). You could try to load-test an SFTP server using PuTTY' psftp tool or similar console client and C funcions like popen/write/read, which are available in any LoadRunner C script regardless of protocol. You might use CVuser Protocol to write such script.
Check this old but still somewhat useful forum discussion for further information.
Not everything can be recorded. Some have to be programmed. Seek an API solution for sftp which runs in C, VB, JavaScript or Java, all of which may be implemented in LoadRunner
You can do sftp using Java vuser protocol. You need to write java code to transfer files. The following code snippet might be helpful.
import lrapi.lr;
import com.jcraft.jsch.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Actions
{
public int init() throws Throwable {
return 0;
}//end of init
public int action() throws Throwable {
JSch jsch = new JSch();
Session session = null;
try {
session = jsch.getSession("userId", "HOST",PORT);
session.setConfig("StrictHostKeyChecking", "no");
session.setPassword("Password");
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelSftp sftpChannel = (ChannelSftp) channel;
sftpChannel.cd("Directory to upload files");
System.out.println("Connection Established");
File file = new File("Local folder to upload files");
sftpChannel.put(new FileInputStream(file),file.getName());
sftpChannel.exit();
session.disconnect();
}
catch (JSchException e)
{
e.printStackTrace();
}
return 0;
}
public int end() throws Throwable {
return 0;
}//end of end
}
I wanted to checking my database table for periodically.So how can i create a webservice and how can i configure it.
basically what you need is, something which is always running and hence can make periodic calls.
There are a number of ways to do it
(Since ASP.NET hence) You can make a Windows Service, and host this service on your server, since server is always running, this Windows Service will make request to your webservice, update database or watever you want
You can use SQL Jobs to do it. You can call a webservice from a job, through a SSIS (Sql Server Integration Service) Package. These packages are very very robust in nature, they can do almost any db activity that you want them to do, including webservice request.
And finally, you can use third party tools such as Quartz.Net
References:
this is how you can call a webservice through a windows service.
this is how you can call a webservice through a ssis package.
this is how you can integrate a SSIS package in a SQL Job
this is how you can create a windows service
this is how you can create a SSIS package
this is how you can get answer/tutorial of almost anything
Example:
simplest of all of these would be a Windows Service. Making a windows service and hosting it on the machine(server) is very easy, use one of the given links (specially the last link). Usually, in Windows Service, you do some activity in OnStart event. you can place a timer inside this OnStart and upon TimerTick(), you can request your webservice.
something like this:
class Program : ServiceBase
{
System.Timers.Timer timer;
static void Main(string[] args)
{
ServiceBase.Run(new Program());
}
public Program()
{
this.ServiceName = "My Service";
}
protected override void OnStart(string[] args)
{
base.OnStart(args);
InitializeTimer();
}
protected override void OnStop()
{
base.OnStop();
//TODO: clean up any variables and stop any threads
}
protected void InitializeTimer()
{
try
{
if (timer == null)
{
timer = new System.Timers.Timer();
timer.Enabled = true;
timer.AutoReset = true;
timer.Interval = 60000 * 1;
timer.Enabled = true;
timer.Elapsed += timer_Elapsed;
}
}
catch (Exception ex)
{
Utility.WriteLog("Exception InitialiseTimer : " + ex.Message.ToString());
}
finally
{
}
}
protected void timer_Elapsed(object source, System.Timers.ElapsedEventArgs e)
{
TimerTick();
timer.Interval = 60000 * Convert.ToDouble(ConfigurationManager.AppSettings["TimerInerval"]);
}
private void TimerTick()
{
try
{
DownloadFromFTPandValidate objDownLoadandValidate = new DownloadFromFTPandValidate();
objDownLoadandValidate.ProcessMain();
}
catch (Exception ex)
{
Utility.WriteLog("Exception InitialiseTimer : " + ex.Message.ToString());
}
}
}
Here, class DownloadFromFTPandValidate wraps the code to db activity. It shd give you an idea.
You will need a job scheduler for periodical task. I recommend you a good one. Check out this link: http://quartznet.sourceforge.net/
Why not using a trigger on your table which runs a stored procedure once data was modified, then use the xp_cmdshell to access the commandline form your stored procedure so you can run for example a batch file or whatever.