Count active sessions in J2EE app deployed on JBoss 3.2.1 - jboss

I manage a J2EE application which is deployed on JBoss 3.2.1. As part of my service to my client I want to provide reports which show the number of active sessions. I have implemented a simple class and a JSP page which retrieve the number of active sessions, but I have discovered a flaw: the process of checking the number of sessions itself creates a new session, and therefore inflates the number of sessions.
Here is the code for my class:
package com.hudsongates;
import javax.servlet.http.*;
public class SessionCount implements HttpSessionListener
{
private static int numberOfSessions = 0;
public void sessionCreated (HttpSessionEvent evt)
{
numberOfSessions++;
}
public void sessionDestroyed (HttpSessionEvent evt)
{
numberOfSessions--;
}
// here is our own method to return the number of current sessions
public static int getNumberOfSessions()
{
return numberOfSessions;
}
}
The JSP page looks like this:
<html>
<head>
<title>Active Sessions</title>
</head>
<body>
activeSessions=<%=com.hudsongates.SessionCount.getNumberOfSessions()%>
</body>
</html>
I would like to change the approach slightly so that instead of using a JSP page, I use a simple batch file. For example, I created a batch file called getSessions.bat:
REM Setup environment
call environment.bat
set LOG_PATH=%INSTALL_PATH%\log
set =%INSTALL_PATH%\lib\app.jar
set CLASSPATH=%INSTALL_PATH%\lib\app.jar
%JDK_HOME%\bin\java -cp "%CLASSPATH%" com.hudsongates.SessionCount.getNumberOfSessions() > %LOG_PATH%\test.log
The problem is that when I execute the batch file I get the following exception:
Exception in thread "main" java.lang.NoClassDefFoundError: com/hudsongates/SessionCount/getNumberOfSessions()
Do I need to add a "main" method to my class? If so, what would it do? Is there a better way of achieving my end goal of accurately counting the number of active sessions? Bear in mind that the session count needs to be written to a log file in the following format:
activeSessions=24
Thanks in advance,
Paul

Two possibilities spring to mind:
Your JSP can be configured to not create a new session. Stick this at the top of your JSP:
<%# page session="false"%>
Alternatively, write a JMX MBean which implements JBoss's ServiceMBean interface, and deploy it as a JBos service. This MBean would query the session count, and would appear on JBoss's JMX console. You can use your web browser to monitor it from there, without interfering with your session count.

The JBoss JMX Console already has a integrated session counter in host=localhost,path=/YOUR_PROJECT,type=Manager
By the way, you should use AtomicInteger or synchronize to take care of concurrency problems.

Related

Keycloak: Add custom extension io.undertow.servlet.ServletExtension

I wanted to add a custom servlet extension to Keycloak which would install a http handler that gets invoked on every request sent to Keycloak and sets up some logging MDC context that our custom SPI code can use for logging the incoming request traces correctly.
Following the docs here I created a custom extension class:
public class UndertowHandlerExtension implements ServletExtension {
#Override
public void handleDeployment(DeploymentInfo deploymentInfo, ServletContext servletContext) {
deploymentInfo.addInnerHandlerChainWrapper(TraceIdCapturingHandler::new);
}
}
And have defined my custom http handler TraceIdCapturingHandler in the same JAR file. I also added a file to META-INF/services/io.undertow.servlet.ServletExtension and set the fully qualified reference to the extension class. I also updated my deployments jboss-deployment-structure.xml and added the following 2 entries as dependencies:
<module name="io.undertow.servlet" />
<module name="javax.servlet.api" />
However, when my deployment is created the extension is not being invoked and my filter is not executing. Is there something I am missing in terms of how to configure Wildfly for Keycloak so that my extension and handler are installed and used correctly?
EDIT:
After doing a bit of digging I realized I was headed down the wrong path. Looked at this repository and I think I need a custom RealResourceProvider as shown here which in turn can install my filter by obtaining an instance of ResteasyProviderFactory and invoking getContainerRequestFilterRegistry().registerSingleton().
Will try this out and report back.
Please see the edit above for my question. I was able to implement a RealmResourceProviderFactory instance that initialized the filters I needed on startup in the init() method:
#Override
public void init(Config.Scope scope) {
log.info("Initializing");
initializeKeycloakFilters();
}
private void initializeKeycloakFilters() {
ResteasyProviderFactory providerFactory = ResteasyProviderFactory.getInstance();
TraceIdCapturingFilter filter = new TraceIdCapturingFilter();
providerFactory.getContainerRequestFilterRegistry().registerSingleton(filter);
}

Setting queueSize option on SEDA

I have a seda queue where i set queueSize option according to the camel documentation
The route i have looks like:
from("seda:someQueue?concurrentConsumers=10&queueSize=10")
.process(someProcessor);
I'm getting the following error due to the queueSize option:
org.apache.camel.FailedToCreateRouteException: Failed to create route....bla bla bla..
There are 1 parameters that couldn't be set on the endpoint. Check the uri if the parameters are spelt correctly and that they are properties of the endpoint. Unknown parameters=[{queueSize=10}].....
[stacktrace continues here]
Can anyone point out what's wrong?
I'm using Java 8, Camel 2.9.13
Notice that the documentation says that the option queueSize is component only, which mean you need to configure it on the SedaComponent instead. In other words you cannot configure it on the endpoint as you do in your route above.
For up to date documentation and better docs on Camel components, then browse github pages at: https://github.com/apache/camel/blob/master/components/camel-seda/src/main/docs/seda-component.adoc
Those docs are up to date and show both component vs endpoint options in different tables, so its easier to know the difference.
For those who have the same question, this is how i use the queueSize now
Initialize a new seda component,
SedaComponent sedaComponent = new SedaComponent();
sedaComponent.setQueueSize(3);
context.addComponent("sedaComponent", sedaComponent);
then use this component at the route like,
from("seda:someEndPoint?concurrentConsumers=5")
.to("sedaComponent:someOtherSedaEndPoint?blockWhenFull=true");
Create a specific queue . it is quarkus example replace Named as bean and ApplicationScoped to Configuration for Spring boot
#ApplicationScoped
public class ConnectionConf {
#Named("NonLimitQueue")
#Produces
public BlockingQueue arrayDeque(){
return new ArrayBlockingQueue(30000);
}
}
camel side
from("seda:queue=#NonLimitQueue")
.convertBodyTo(String.class).log("${body}")
Replace queueSize
with
size(query param in apache document)
from("seda:someQueue?concurrentConsumers=10&queueSize=10")
.process(someProcessor);

AEM- Activating page references in node properties along with the page

I am working on AEM 6.2 and have created a custom replication module. I have some properties in my page's child nodes under jcr:content,whose values are the path field to another pages in the same website.
when I am activating a page, I need to activate the pages referenced in the properties too.
For example, my page path is "/content/project/family/subfamily/TestPage"
I need to activate a page path in the node property "pathVal" under
"/content/project/family/subfamily/TestPage/abc123/jcr:content".
How do I do this?
I am not sure what you mean by
custom replication module
Writing a replication Preprocessor (see docs) may be a way to go. The replication process collects all implementations of that interface using the whiteboard pattern and then cycles through them invoking each one of them.
#Component
#Service
public class ReferencedPagePreprocessor implements Preprocessor {
#Reference
private Replicator replicator;
#Reference
private ResourceResolverFactory resolverFactory;
public void preprocess(ReplicationAction action, ReplicationOptions options) {
// some extra filtering to avoid the calculation if it's not the expected page type
String resourcePath = action.getPath();
ResourceResolver resolver = getResolver();
Resource resource = resolver.resolve(resourcePath);
String referencedResourcePath = resource.adaptTo(ValueMap.class).get("pathVal", String.class);
replicator.replicate(resolver.adaptTo(Session.class), ReplicationActionType.ACTIVATE, referencedResourcePath);
}
private ResourceResolver getResolver() {
...
}
}
Take also a look into a sample implementation in ACS AEM Commons
If I understand correctly either you have implemented your own workflow process that activates the page or you would have followed the approach of Preprocessor as outlined by Mateusz ChromiƄski.
In case you have written your own workflow process that invokes Replicator API you could effectively add logic to get referenced paths and call activate on them using Replicator API

Mybatis hybrid configuration system

I am writing a CLI app with Mybatis. In my app, when i go to different menus, it prompts for the user and password for the particular database that menu goes against.
I want to use Guice and Mybatis to handle all this but i have a slight problem. I want to use the XML config file to handle the mybatis config per database, but the user and pass from each connection has to come from the UI. So basically, i want to load mybatis xml file for a particular connection, then insert the credentials for the particular connection the user typed in, then bind those to the guice injector for that set of menus.
I can do it in java with a property object pretty easy, but i can't figure out how to do it with loading the XML first, then augmenting it with certain settings before loading.
Has anyone tried this?
If you are using mybatis guice this can be done by providing your dataSourceProvider for MyBatisModule like this:
Class<? extends Provider<DataSource>> dataSourceProviderType = YourDataSourceProvider.class;
Injector injector = Guice.createInjector(
new MyBatisModule() {
#Override
protected void initialize() {
bindDataSourceProviderType(dataSourceProviderType);
// other initialization ...
}
},
// other modules
);
YourDataSourceProvider should be able to create DataSource using credentials gotten from UI.
In this case you still can use xml mappers for mybatis.

How to do error handling in web application written in Perl (CGI.pm)?

When writing / maintaining web application written in Perl using CGI.pm, how should I handle errors (exceptions)? Webapp in question can be deployed as plain CGI app, as FastCGI app (using CGI::Fast), and as mod_perl app using ModPerl::Registry handler.
I mean here handling errors like page not found, or configuration forbids given action, or some external command used in the app failed (like e.g. cannot connect to the database).
Edit: added 2010-12-14.
The example code flow could look like this:
sub run {
...
run_request();
...
}
sub run_request {
...
$actions{$cgi->param('a')}->();
...
}
sub action_foo {
foo_body()
}
sub foo_body {
check_something()
or handle_error(some description);
}
I mean here that error might have be to be thrown / handled in some nested call, and not only in the action handler / route handler.
Pass the appropriate status code to the header method as per Creating A Standard HTTP Header