Embedded jetty implementing HttpSessionListener - jetty

I am trying to implementing HttpSessionListener interface with embedded jetty with proxy servlet, I have registered SessionListener, but it is not getting invoked at all, here is the code,
public class JettyProxy {
public static void main(String[] args) throws Exception {
Server server = new Server();
CustomProxyServlet customProxyServlet = new CustomProxyServlet();
ServerConnector connector = new ServerConnector(server);
connector.setPort(8888);
server.addConnector(connector);
ConnectHandler proxy = new ConnectHandler();
server.setHandler(proxy);
ServletContextHandler context = new ServletContextHandler(proxy, "/",
ServletContextHandler.SESSIONS);
ServletHolder proxyServlet = new ServletHolder(customProxyServlet);
context.addServlet(proxyServlet, "/*");
if (context.getSessionHandler() == null) {
System.out.println("Session handler is null");
} else {
System.out.println("Session handler is not null");
}
if (context.getSessionHandler().getSessionManager() == null) {
System.out.println("Managaer it null");
} else {
System.out.println("Manager is not null");
}
context.getSessionHandler().addEventListener(new CustomSessionHandler());
server.start();
server.join();
}
}
SessionHandler is not null, session creating events are not getting triggered, please help me, what is the procedure get session events?

you should have a SessionManager. i usually use :
org.eclipse.jetty.server.session.HashSessionManager.HashSessionManager()
and
org.eclipse.jetty.server.session.SessionHandler.SessionHandler(SessionManager manager)
then you should set the handler for the context
context.setHandler(sessionHandler);
sessionHandler.addEventListener("Your Session Listener");

Related

AddSingleton won't accept AddSerilog

I'm facing an issue where I'm trying to write a more smart console app with logging and configuration available.
This is what I have so far:
namespace Client
{
public class Program
{
public static IConfigurationRoot Configuration;
private static int Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.WriteTo.Console(Serilog.Events.LogEventLevel.Debug)
.MinimumLevel.Debug()
.Enrich.FromLogContext()
.CreateLogger();
try
{
MainAsync(args).ConfigureAwait(false);
return 0;
}
catch
{
return 1;
}
}
private static async Task MainAsync(string[] args)
{
// Create service collection
Log.Information("Creating service collection");
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
// Create service provider
Log.Information("Building service provider");
IServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
try
{
Log.Information("Starting service");
await serviceProvider.GetService<App>().Run();
Log.Information("Ending service");
}
catch (Exception ex)
{
Log.Fatal(ex, "Error running service");
throw;
}
finally
{
Log.CloseAndFlush();
}
}
private static void ConfigureServices(IServiceCollection services)
{
// Add logging
services.AddSingleton(
LoggerFactory.Create(
builder => { builder.AddSerilog(dispose: true); }));
services.AddLogging();
// Build configuration
Configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetParent(AppContext.BaseDirectory).FullName)
.AddJsonFile("appSettings.json", false)
.Build();
// Add access to generic IConfigurationRoot
services.AddSingleton(Configuration);
// Add app
services.AddTransient<App>();
}
}
}
I'm facing an issue in ConfigureServices method on line builder.AddSerilog for the life of me, I cannot figure out why it is not able to resolve AddSerilog
I was missing a package: Serilog.Extensions.Logging
For some reason, VS or even Resharper was not able to suggest this.

Can't connect to GRPC server which is deployed on AWS ECS

I have a GRPC server written on C#.
internal class Program
{
internal static void Main(string[] args)
{
using (var waitHandle = new AutoResetEvent(false))
{
void OnConsoleOnCancelKeyPress(object o, ConsoleCancelEventArgs e)
{
e.Cancel = true;
// ReSharper disable once AccessToDisposedClosure
waitHandle.Set();
}
Console.CancelKeyPress += OnConsoleOnCancelKeyPress;
var config = new AppConfig(new ConfigurationBuilder()
.AddJsonFile("appsettings.json", false)
.Build());
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterModule(new Module());
containerBuilder.RegisterModule(new Data.Module(config.Region, config.TablePrefix));
using (var container = containerBuilder.Build())
{
var buyRatesService = container.Resolve<BuyRatesService>();
var logger = container.Resolve<ILogger<Program>>();
var server = new Server
{
Services =
{
BuyRates.BindService(buyRatesService)
},
Ports = {new ServerPort("0.0.0.0", 50051, ServerCredentials.Insecure)}
};
try
{
server.Start();
logger.LogDebug("Service started");
waitHandle.WaitOne();
}
catch (Exception e)
{
logger.LogCritical("Application terminated unexpectedly. Exception {#exception}", e);
}
finally
{
server.ShutdownAsync().Wait();
Console.CancelKeyPress -= OnConsoleOnCancelKeyPress;
}
}
}
}
}
It works fine locally. I deploy it to ecs instance(Docker). The container port is 50051. ALB and Route 53 are used.
When I'm trying to connect to someroute54uri.net:50051 I get an error
Grpc.Core.RpcException: Status(StatusCode=Unavailable, Detail="Connect Failed").
In case when I'm trying to connect to someroute54uri.net, I get an error
Grpc.Core.RpcException: Status(StatusCode=Unavailable, Detail="Trying to connect an http1.x server").
Thanks!.
Please, let me know if additional information helps to solve the issue.

DataSource connections pool

I have a data source configured with its connections pool ready to use, and it is exposed to my application via JDNI, but the code my colleagues wrote actually opens and closes a connection for every query. How does WSO2 handle this? Does it really close the connection given by the pool, or it ignores the close and just considers this connection free to be added back to the pool and ready to be used by any other client?
Connection conn = null;
CallableStatement cStmt = null;
try {
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put("java.naming.factory.initial", "org.wso2.carbon.tomcat.jndi.CarbonJavaURLContextFactory");
Context initContext = new InitialContext(environment);
DataSource ds = (DataSource) initContext.lookup("jdbc/tvaccount");
if (ds != null) {
conn = ds.getConnection();
cStmt = conn.prepareCall("{call getAccountStatusAttr(?)}");
cStmt.setString("pUserLogin", userName);
cStmt.execute();
}
} catch (Exception e) {
log.error("Exception while getting account status: ", e);
} finally {
if (cStmt != null) {
try {
cStmt.close();
} catch (SQLException e) {
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
}
}
}
Have you added this java code as a JAR file in WSO2 ESB and then accessed the method by using class mediator? if this is the case then it behaves like a normal java code wherein once the query is executed the connection will be closed.

jetty 9.4 share sessions among different contexts

I recently upgraded from jetty 9.3.11 to 9.4.6 . Since 9.4.x does not support HashSessionManager, I created my own custom SessionHandler. But when i attach this SessionHandler to the WebAppContext then the context becomes null when trying to access from servlets. there are no errors thrown in the logs.
Relevant section of code:
MyCustomSessionHandler sessionHandler = new MyCustomSessionHandler();
HandlerCollection handlers_ = new HandlerCollection(true);
COntextHandlerCollection chc_ = new ContextHandlerCollection();
for(WebAppConfig wap: webAppConfigs) //webappconfig a POJO from where I am getting webapp configs
{
String path = wap.getPath();
String warFile = wap.getWarFile();
WebAppContext context =
new WebAppContext(chc_, warFile, path);
// context.setSessionHandler(new SessionHandler()); // this one works.
context.setSessionHandler(sessionHandler); // this one doesnt work.
for (ServletConfig servletConfig: wap.getServletConfigs()) //ServletConfig is another POJO to get servlet configs
{
String servletName = servletConfig.getName();
String servletPath = servletConfig.getPath();
Servlet servlet = servletConfig.getServlet();
ServletHolder servletHolder = new ServletHolder(servlet);
context.addServlet(servletHolder, servletPath);
}
}
handlers_.setHandlers(new Handler[] { chc_, new DefaultHandler()});
server_.setHandler(handlers_);
Sample of my custom Session handler
public class MyCUstomSessionHandler extends SessionHandler
{
public MyCustomSessionHandler()
{
super();
}
public void setSecureCookies(boolean secureCookies)
{
getSessionCookieConfig().setSecure(secureCookies);
}
public void setHttpOnly(boolean httpOnly)
{
getSessionCookieConfig().setHttpOnly(httpOnly);
}
public void setMaxCookieAge(int age)
{
getSessionCookieConfig().setMaxAge(age);
}
}
Further clarification: It happens because I create a singleton sessionhandler and share it across different WepAppContext as a way of sharing sessions among them. This method seemed work fine without issues in 9.3 but doesn't work with new session management in 9.4.
Any help to solve this problem is appreciated.
I solved it by
setting cookie path to root ("/")
extending the getSession() function of SessionHandler to loop through all the contexts to check if session is created for the cookie in any other context.
/* check all contexts for sessions*/
public Session getSession(String id)
{
Session session = getLocalSession(id);
if (session == null)
{
for (SessionHandler manager: getSessionIdManager().getSessionHandlers())
{
if (manager.equals(this) ||
!(manager instanceof CustomSessionHandler))
{
continue;
}
session = ((CustomSessionHandler)manager).getLocalSession(id);
if (session != null)
{
break;
}
}
// should we duplicate sessions in each context?
// will we end up with inconsistent sessions?
/*
if (externalSession != null)
{
try
{
getSessionCache().put(id, externalSession);
}
catch (Exception e)
{
LOG.warn("Unable to save session to local cache.");
}
}
*/
}
return session;
}
/* ------------------------------------------------------------ */
/**
* Get a known existing session
* #param id The session ID stripped of any worker name.
* #return A Session or null if none exists.
*/
public Session getLocalSession(String id)
{
return super.getSession(id);
}

Unit Test for a Java Component accessing ActiveMq in Mule Flow

I have the below Java Class which retrieve messages from JMS queue. This class is invoked in a mule flow. Could you please advice on how I can write a Junit for this class? I have tried to create a standalone broker but I am having trouble
public Object getMessages(final MuleEventContext eventContext)
{
final String consumerID = eventContext.getMessage().getProperty("consumerID", PropertyScope.INVOCATION);
final String messageSelector = "ConsumerID = '" + consumerID + "'";
JmsConnector amqConnector = (JmsConnector) eventContext.getMuleContext().getRegistry().lookupConnector("Active_MQ");
ConnectionFactory factory = amqConnector.getConnectionFactory();
Connection connection = null;
List<String> listOfMessages = null;
try
{
connection = factory.createConnection();
//Consumer Settings
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue(queuename");
MessageConsumer consumer = session.createConsumer(queue, messageSelector);
//Browser Settings
Session sessionBrowser = amqConnector.getSession( false, false );
Queue queueBrowser = sessionBrowser.createQueue( queuename );
QueueBrowser qBrowser = sessionBrowser.createBrowser( queueBrowser, messageSelector );
Enumeration<Message> enumeration = qBrowser.getEnumeration();
connection.start();
listOfMessages = new ArrayList<String>();
while (enumeration.hasMoreElements())
{
enumeration.nextElement();
Message message = consumer.receive();
TextMessage msg = (TextMessage) message;
listOfMessages.add(msg.getText());
}
//Close Browser Settings
qBrowser.close(); sessionBrowser.close();
//Close Consumer Settings
consumer.close(); session.close();
//Close Connection
connection.close();
}
catch ( Exception e )
{
throw new RuntimeException("Unable to retrieve messages from Queue "+ e);
}
}
You can create FunctionalTestCase, and then:
Test the class directly by calling the method, or
Test the whole scenario by calling the flow
public class MessageServiceTest extends FunctionalTestCase {
#Test
public void testJavaClass() throws Exception {
MuleEventContext eventContext = MuleTestUtils.getTestEventContext("", MessageExchangePattern.REQUEST_RESPONSE, muleContext);
MessageService messageService = new MessageService();
assertNotNull(messageService.getMessages(eventContext));
}
#Test
public void testFlow() throws Exception {
MuleEvent event = runFlow("messageserviceFlow");
MuleMessage message = event.getMessage();
assertNotNull(message);
assertNotNull(message.getPayload());
}
protected String getConfigResources() {
return "messageservice.xml";
}
}