Adding a servlet to run in Intershop 7.4 application server context - servlets

I'm trying to include a 3rd party servlet to run in our IS7 application server's context. How would I go about adding the servlet and mapping to the web.xml?
In the knowledge base I have only found information regarding Enfinity Suite 6. None of the steps provided seem to work.
EDIT:
I found a proposed solution for IS7 using Guice and binding the servlet via a specific Servlet module like
package com.intershop.test;
import com.google.inject.servlet.ServletModule;
public class MyServletModule extends ServletModule
{
#Override
protected void configureServlets()
{
bind(MyServlet.class).in(Singleton.class);
serve("/my/*").with(MyServlet.class);
}
}
I have added my ServletModule to the objectgraph.properties file but my servlet still isn't called when I try accessing it.
Any suggestions?

I know that this works in ICM 7.7 but I believe it has been around since 7.4.
You may use the Guice Servlet Extension.
1.Declare dependency to the Guice Servlet in your cartridge build.gradle. Example:
dependencies
{
...
compile group: 'com.intershop.platform', name: 'servletengine'
compile 'com.google.inject.extensions:guice-servlet'
...
}
2.Define a servlet module in the cartridge objectgraph.properties. Example:
global.modules = com.example.modules.DemoServletModule
3.Implement your servlet. Example:
public class DemoServlet extends HttpServlet
{
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
resp.getWriter().append("Hello, world!");
}
}
4.Create the module implementation. Gotcha: The name should start with /servlet/ as pointed in the comments. Example:
import javax.inject.Singleton;
import com.google.inject.servlet.ServletModule;
public class DemoServletModule extends ServletModule
{
#Override
protected void configureServlets()
{
bind(DemoServlet.class).in(Singleton.class);
serve("/servlet/DEMO/*").with(DemoServlet.class);
}
}
4.Build, restart, try. Example:
GET /servlet/DEMO/hey HTTP/1.1
Host: example.com:10054
....
Reposnse:
Hello, world!
UPDATE:
If you would like that your servlet is visible through the webadapter you have to allow it.
1.Open IS_SHARE\system\config\cluster\webadapter.properties
2.Navigate to this section:
## The list of servlets, which can be accessed through the generic
## .servlet mapping. The WebAdapter forwards only requests of the form
## /servlet/<group><servlet.allow.x>...
3.Add entry for your servlet. Example:
servlet.allow.4=/DEMO
4.Access the servlet on a similar URL:
https://example.com/INTERSHOP/servlet/WFS/DEMO/hey

Related

#WebFilter seems to ignore included Javascript files

( this is regarding Java EE / Servlets WebFilters)
I am currently trying to write a WebFilter which catches every request made to the web application.
However, I noticed that the WebFilter does not see requests made within <script> tags.
The HTML-Page which is being served contains a stylesheet...
<link rel="stylesheet" href="/webjars/bootstrap/4.1.0/css/bootstrap.min.css">
...and three Javascript-includes...
<script src="/webjars/jquery/3.0.0/jquery.min.js"></script>
<script src="/webjars/popper.js/1.14.1/popper.min.js"></script>
<script src="/webjars/bootstrap/4.1.0/js/bootstrap.min.js"></script>
The #WebFilter, however, only sees requests to the root page (GET /) and to the stylesheet, shown in the logs created by the filter below.
12:04:51,909 INFO Init
12:04:51,909 INFO doFilter
12:04:51,909 INFO ServletRequest: HttpServletRequestImpl [ GET / ]
12:04:51,959 INFO doFilter
12:04:51,959 INFO ServletRequest: HttpServletRequestImpl [ GET /webjars/bootstrap/4.1.0/css/bootstrap.min.css ]
The Implementation of the WebFilter looks like this:
#WebFilter(filterName = "webjarFilter", urlPatterns = "/*")
public class WebJarFilter implements Filter {
private Logger logger = LoggerFactory.getLogger(getClass());
public void init(FilterConfig filterConfig) throws ServletException {
logger.info("Init");
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
logger.info("doFilter");
logger.info("ServletRequest: {}", servletRequest);
filterChain.doFilter(servletRequest, servletResponse);
}
public void destroy() {
logger.info("destroy");
}
}
The web.xml file contains following mapping:
<filter-mapping>
<filter-name>webjarFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
My question now is:
Can somebody tell me why the filter does not catch the requests which should be generated from the <script> tags?
Observations and additional Info:
I am testing on Wildfly 12 with the Java EE 7
Directly opening the Javascript-Files will trigger the filter
When Javascript files with a wrong path are referenced, the filter sees the requests. Only inclusions of Javascript-files with the correct path are not seen by the filter
Looks like I figured it out myself.
This is actually a result of Firefox behavior.
When calling the same server from Chrome, the filter sees all requests.
Apparently there is some caching mechanism involved within Firefox which applies to scripts.

Run a code when the war is deployed [duplicate]

I need to get some configuration and connect to external resources/objects/systems somewhere and store it in application scope.
I can see two ways to setup my application:
Overriding the init() in the existing servlets and required code there and keeping all constructed objects inside that same servlet.
Having some kind of an initialisation servlet and using its init() to do the work. Then storing created objects in ServletContext to share it with my other servlets.
Which out of above is better approach? Is there any better way to share objects between servlets? Calling them directly from one another or so...?
None of both is the better approach. Servlets are intended to listen on HTTP events (HTTP requests), not on deployment events (startup/shutdown).
CDI/EJB unavailable? Use ServletContextListener
#WebListener
public class Config implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
// Do stuff during webapp's startup.
}
public void contextDestroyed(ServletContextEvent event) {
// Do stuff during webapp's shutdown.
}
}
If you're not on Servlet 3.0 yet and can't upgrade (it would be about time because Servlet 3.0 was introduced more than a decade ago), and thus can't use #WebListener annotation, then you need to manually register it in /WEB-INF/web.xml like below:
<listener>
<listener-class>com.example.Config</listener-class>
</listener>
To store and obtain objects in the application scope (so that all servlets can access them), use ServletContext#setAttribute() and #getAttribute().
Here's an example which lets the listener store itself in the application scope:
public void contextInitialized(ServletContextEvent event) {
event.getServletContext().setAttribute("config", this);
// ...
}
and then obtain it in a servlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
Config config = (Config) getServletContext().getAttribute("config");
// ...
}
It's also available in JSP EL by ${config}. So you could make it a simple bean as well.
CDI available? Use #Observes on ApplicationScoped.class
import jakarta.enterprise.context.ApplicationScoped; // And thus NOT e.g. jakarta.faces.bean.ApplicationScoped
#ApplicationScoped
public class Config {
public void init(#Observes #Initialized(ApplicationScoped.class) ServletContext context) {
// Do stuff during webapp's startup.
}
public void destroy(#Observes #Destroyed(ApplicationScoped.class) ServletContext context) {
// Do stuff during webapp's shutdown.
}
}
This is available in a servlet via #Inject. Make it if necessary also #Named so it's available via #{config} in EL as well.
Noted should be that this is new since CDI 1.1. If you're still on CDI 1.0 and can't upgrade, then pick another approach.
In case you're curious how to install CDI on a non-JEE server such as Tomcat, head to: How to install and use CDI on Tomcat?
EJB available? Consider #Startup#Singleton
#Startup
#Singleton
public class Config {
#PostConstruct
public void init() {
// Do stuff during webapp's startup.
}
#PreDestroy
public void destroy() {
// Do stuff during webapp's shutdown.
}
}
This is available in a servlet via #EJB. The difference with other approaches is that it's by default transactional and in case of #Singleton also read/write locked. So if you would ever need to inject a random EJB (e.g. #Stateless) into a #WebListener or an #ApplicationScoped then you could basically as good merge both into a single #Startup #Singleton.
See also:
How to run a background task in a servlet based web application?
ServletContainerInitializer vs ServletContextListener
How do I force an application-scoped bean to instantiate at application startup?

Implementing WebSocket on Spring MVC based Server

I searched a lot about implementing WebSocket/XMPP on Spring MVC based server but couldn't reach to a concrete answer. So here is my requirement
Receive a message from a client (in my case it will be a android/iOS mobile) via WebSocket/XMPP on tomcat server and parse the actual message at server side
Send a message from server app to WebSocket/XMPP client
If somebody could help me to point on some good tutorial or demo code, it would be a great help.
run Tomee 1.5.2
http://openejb.apache.org/downloads.html
activate the ActiveMQ JMS Server. create an OpenEJB configuration.
http://www.mail-archive.com/users#openejb.apache.org/msg04327.html
setup an XMPP ActiveMQ server protocol listener (in the activemq.xml)
in your Spring services configuration, create a Spring JMS listener (Spring ListenerContainer) configuration on the Topic/Queue.
you can use the JmsTemplate to push a message out to the Queue/Topic via ActiveMQ, the XMPP client will receive the message.
Enjoy!
BTW: This is exactly what I am in the middle of setting up right now...still learning.
check this out: www.xchat.io. It was built based on Asynchronous Spring MVC (DefferredResult, you know), XMPP, and jQuery. it's promising.
I am not sure if this is just perfect way to achieve or not, but for now I have found a solution and it would be glad to share it here.
There are two steps that you have to done.
1. Instead of ordinary HTTPServlet sub class, create a sub class of WebSocketServlet and
2. Create a sub class of MessageInbound class and override its required methods.
P.S. : Only latest version of tomcat supports WebSocket (apache tomcat 7.0.42 or higher).
Here is a WebSocket class.
public class WsChatServlet extends WebSocketServlet {
private static final long serialVersionUID = 1456546233L;
#Override
protected StreamInbound createWebSocketInbound(String protocol,
HttpServletRequest request) {
return new IncomingMessageHandler();
}
}
And this is a simple class which can send/receive message (String/binary).
public class IncomingMessageHandler extends MessageInbound {
#Override
public void onOpen(WsOutbound outbound) {
logger.info("Open Client.");
}
#Override
public void onClose(int status) {
logger.info("Close Client.");
}
#Override
public void onTextMessage(CharBuffer cb) throws IOException {
logger.info("Text Message received:" + cb.toString());
}
#Override
public void onBinaryMessage(ByteBuffer bb) throws IOException {
}
public synchronized void sendTextMessage(String message) {
try {
CharBuffer buffer = CharBuffer.wrap(message);
this.getMyoutbound().writeTextMessage(buffer);
this.getMyoutbound().flush();
} catch (IOException e) {
// Handle Exception
}
}
}

Seam and ServletOutputStream - flush is not immediately visible

I am converting a 6 year old application to Seam 2.2.
The application is used to run in java 1.4 and weblogic 8.
It only uses jsp and servlet.
In one servlet I use:
public void doGet (HttpServletRequest req,HttpServletResponse res) throws ServletException,IOException
{
//...
ServletOutputStream out = = res.getOutputStream();
// displaying a lot of messages
// after each println() I do a flush()
out.println("lots of messages.....");
out.flush();
out.close();
//...
}
When running the application the messages were immediately seen in the browser.
When I run this using Seam 2.2 in Weblogic 10 and Java 1.6 the messages are not immediately seen in the browser.
Only when the servlet is finished running.
Can I change something to fix this?
I do not want to change/convert the servlet into a Seam component. The servlet is running fine. The only thing is the flushing of messages to the browser window which only happens after the servlet has stopped running.
Could it be that the reason is that the servlet now goes through the Seam filter:
<filter>
<filter-name>Seam Filter</filter-name>
<filter-class>org.jboss.seam.servlet.SeamFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Seam Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
The reason is probably that the request goes through the SeamFilter, as you supposed.
I think it's not the SeamFilter itself that buffer the data stream from your servlet but the Ajax4Jsf filter that is invoked in the filter chain.
If you have RichFaces in the classpath there is a seam component that registers the Ajax4jsf filter in the chain. Namely, the Seam component is org.jboss.seam.web.ajax4jsfFilter.
If you don't need RichFaces try removing it from the classpath. If you need it, I suggest that you override org.jboss.seam.web.ajax4jsfFilter in order to skip the Ajax4Jsf filter for requests directed to your servlet.
Another possible solution is converting your servlet in a filter as a Seam component (see #Filter annotation) and positioning it at the beginning of the chain with the around attribute. Something like:
#Name("FormerServlet")
#Scope(STATELESS)
#BypassInterceptors
#Filter(around = "org.jboss.seam.web.ajax4jsfFilterInstantiator")
public class FormerServletFilter implements Filter
{
protected void init(FilterConfig filterConfig) throws Exception
{
}
protected void doDestroy()
{
}
/**
* Performs the filtering for a request.
*/
protected void doFilter(final HttpServletRequest request, final HttpServletResponse response,
final FilterChain chain) throws Exception
{
if (thisRequestShoudBeManagedByMyServlet(request) )
{
// do here what you previously did in the servlet
} else
{
// go ahead with the Seam lifecycle
chain.doFilter(request, response);
}
}
You're running a servlet - there's nothing to do with Seam here. I suspect you need to re-evaluate your design, as there's not really an exact translation from servlet to Seam structure.

Using special auto start servlet to initialize on startup and share application data

I need to get some configuration and connect to external resources/objects/systems somewhere and store it in application scope.
I can see two ways to setup my application:
Overriding the init() in the existing servlets and required code there and keeping all constructed objects inside that same servlet.
Having some kind of an initialisation servlet and using its init() to do the work. Then storing created objects in ServletContext to share it with my other servlets.
Which out of above is better approach? Is there any better way to share objects between servlets? Calling them directly from one another or so...?
None of both is the better approach. Servlets are intended to listen on HTTP events (HTTP requests), not on deployment events (startup/shutdown).
CDI/EJB unavailable? Use ServletContextListener
#WebListener
public class Config implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
// Do stuff during webapp's startup.
}
public void contextDestroyed(ServletContextEvent event) {
// Do stuff during webapp's shutdown.
}
}
If you're not on Servlet 3.0 yet and can't upgrade (it would be about time because Servlet 3.0 was introduced more than a decade ago), and thus can't use #WebListener annotation, then you need to manually register it in /WEB-INF/web.xml like below:
<listener>
<listener-class>com.example.Config</listener-class>
</listener>
To store and obtain objects in the application scope (so that all servlets can access them), use ServletContext#setAttribute() and #getAttribute().
Here's an example which lets the listener store itself in the application scope:
public void contextInitialized(ServletContextEvent event) {
event.getServletContext().setAttribute("config", this);
// ...
}
and then obtain it in a servlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
Config config = (Config) getServletContext().getAttribute("config");
// ...
}
It's also available in JSP EL by ${config}. So you could make it a simple bean as well.
CDI available? Use #Observes on ApplicationScoped.class
import jakarta.enterprise.context.ApplicationScoped; // And thus NOT e.g. jakarta.faces.bean.ApplicationScoped
#ApplicationScoped
public class Config {
public void init(#Observes #Initialized(ApplicationScoped.class) ServletContext context) {
// Do stuff during webapp's startup.
}
public void destroy(#Observes #Destroyed(ApplicationScoped.class) ServletContext context) {
// Do stuff during webapp's shutdown.
}
}
This is available in a servlet via #Inject. Make it if necessary also #Named so it's available via #{config} in EL as well.
Noted should be that this is new since CDI 1.1. If you're still on CDI 1.0 and can't upgrade, then pick another approach.
In case you're curious how to install CDI on a non-JEE server such as Tomcat, head to: How to install and use CDI on Tomcat?
EJB available? Consider #Startup#Singleton
#Startup
#Singleton
public class Config {
#PostConstruct
public void init() {
// Do stuff during webapp's startup.
}
#PreDestroy
public void destroy() {
// Do stuff during webapp's shutdown.
}
}
This is available in a servlet via #EJB. The difference with other approaches is that it's by default transactional and in case of #Singleton also read/write locked. So if you would ever need to inject a random EJB (e.g. #Stateless) into a #WebListener or an #ApplicationScoped then you could basically as good merge both into a single #Startup #Singleton.
See also:
How to run a background task in a servlet based web application?
ServletContainerInitializer vs ServletContextListener
How do I force an application-scoped bean to instantiate at application startup?

Resources