Modify Servlet parameters - java

I've a GWT Servlet running in a Tomcat 6.0 server. This server acts as a proxy to another service. This final service may be running in different IPs and/or ports in my network.
How can I configure my GWT Servlet to connect to any of my services without manually modifying the web.xml file?
I'm initializing my servlet with:
<!-- Servlets -->
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.proxy.MyServletServiceImpl</servlet-class>
<init-param>
<param-name>serverAddress</param-name>
<param-value>192.168.1.10</param-value>
</init-param>
<init-param>
<param-name>serverPort</param-name>
<param-value>55005</param-value>
</init-param>
</servlet>
From inside my MyServletSerciveImpl.java file I'm doing
private void loadConfig() {
ServletConfig config = this.getServletConfig();
serverAddress = config.getInitParameter("serverAddress");
serverPort = Integer.valueOf(config.getInitParameter("serverPort"));
}
My ideal case would be that this configuration is the default, but applying some configuration file (a properpies file, xml, ini, cfg, .....) I could overwrite the default web.xml values.
Any idea how to do that?
Thanks.

For true dynamic configuration, you can expose a configuration object as a jmx bean, and have your servlet use that bean.
An intermediate solution is to put the configuration in a different file, as xml or properties, or in a db table, and read from it periodically in a background thread.

For completeness:
public class MyServiceImpl extends RemoteServiceServlet implements
MyService {
private void loadConfig() {
InputStream inStream = this.getServletContext().getResourceAsStream("/WEB-INF/config.properties");
Properties properties = new Properties();
try {
properties.load(inStream);
// properties.getProperty("myValue");
} catch (IOException e) {
Log.error(e.getMessage());
e.printStackTrace();
}
}
....
}

Related

REST WebServise - how to use service like a singleton?

My rest application contains a service and I need to make this service to act like a singleton to save a state of the service.
a service:
#Path("/script")
public class ScriptEngineProvider {
private AtomicInteger idCounter;
public ScriptEngineProvider() {
System.out.println("before AtomicInteger");
idCounter = new AtomicInteger();
}
#POST
public Response executeScript( String x ) {
idCounter.incrementAndGet();
System.out.println("counter " + idCounter);
...
a client besides all other code has:
WebTarget webTarget = client.target("http://localhost:8080/NashornEngine/rest").path("script");
web.xml
<url-pattern>/rest/*</url-pattern>
With the above configuration the application works but with every request the variable idCounter creates so idCounter is allways 1.
Now I use next class to make the ScriptEngineProvider to be a singleton:
#ApplicationPath("/services")
public class NashornApplication extends Application {
private Set<Object> singletons = new HashSet<Object>();
public NashornApplication() {
singletons.add(new ScriptEngineProvider());
}
#Override
public Set<Object> getSingletons() {
return singletons;
}
}
The problem is that I get The requested resource is not available with request:
//path services was added
WebTarget webTarget = client.target("http://localhost:8080/NashornEngine/rest").path("services").path("script");
What is the problem with this config?
try this:
#Singleton // this is the important line
#Path("/script")
public class ScriptEngineProvider {
private AtomicInteger idCounter;
public ScriptEngineProvider() {
System.out.println("before AtomicInteger");
idCounter = new AtomicInteger();
}
#POST
public Response executeScript( String x ) {
idCounter.incrementAndGet();
System.out.println("counter " + idCounter);
...
#ApplicationPath effectively serves the same purpose as the url-mapping. But only one can be used. You use #ApplicationPath with an Application subclass when you don't want to use web.xml configuration. To go web.xml-less, you need to make sure of two things
You are deploying to a 3.x servlet container.
You have the dependency that supports the servlet pluggability. See more here
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey2.version}</version>
</dependency>
It's also possible to use an Application subclass without the #ApplicationPath, which will then use the url-mapping to map the Jersey servlet. For example
<servlet>
<servlet-name>MyApplication</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.pkg.YourApplication</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>MyApplication</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
Which ever way you choose, either the url-mapping path will be used, or the #ApplicationPath value will be used, but not both. So in your case, if you do with no web.xml configuration, the path would not include the /rest in the url-mapping. And if you go with the above web.xml configuration, then you should get rid of the #ApplicationPath on your Application subclass, that url you would use would with /rest, with no /services.
The reason you keep getting one is because
The default behavior is to create a new resource class for every request
Your Application subclass is not being used, and your web.xml configuration is being used, where you are package scanning.
Review the information from this post, and make the changes accordingly.

Initializing Jetty+Jersey

I'm trying to initialize Jetty with the following code:
URI baseUri = UriBuilder.fromUri("http://localhost/").port(config.getPort()).build();
ResourceConfig resConfig = new ResourceConfig(GetFutureTimetableCommand.class);
Server server = JettyHttpContainerFactory.createServer(baseUri, resConfig);
WebAppContext context = new WebAppContext();
context.setDescriptor("WebContent/WEB-INF/web.xml");
context.setResourceBase("WebContent");
context.setContextPath("rest/*");
context.setParentLoaderPriority(true);
server.setHandler(context);
server.start();
My Resource looks like this:
#Path("/timetable")
public class GetFutureTimetableCommand extends CMSCommand {
#GET
#Produces(MediaType.APPLICATION_JSON)
public CMSBean execute(#PathParam("param") String params) {
System.out.println("GOOD");
return new FutureTimetable(8202L, DateTime.now().plusDays(2));
}
}
And from the browser:
http://localhost:8080/rest/timetable
But nothing really happens, what am I doing wrong??
I have found that enabling MBeans with monitoring statistics invaluable when trying to determine why a resource isn't executing.
Add the below to your Jersey Servlet definition in your web.xml and connect JVisualVM or JConsole to see lots of data on deployed resources.
<init-param>
<param-name>jersey.config.server.monitoring.statistics.mbeans.enabled</param-name>
<param-value>true</param-value>
</init-param>
I appreciate this isn't an answer to your problem, but hopefully should help you find it.
Will
It seems only the root context path is taken into account when jersey is used together with jetty as per Jersey documentation (others are just ignored):
https://jersey.java.net/documentation/latest/deployment.html
You probably need to change the context path with:
context.setContextPath("/");

How to configure ContextLoaderListener to not look for applicationContext.xml

I'm trying to steer clear of XML based configuration within my application and would like to maintain all configuration within the code. Currently the org.springframework.web.context.ContextLoaderListener looks for applicationContext.xml.
Is it possible for me to turn that off so it doesn't require that file?
Currently main() looks like this...
public static void main(String[] args) throws IOException {
final HttpServer server = HttpServer.createSimpleServer(".", 8181);
WebappContext ctx = new WebappContext("Socket", "/");
//allow spring to do all of it's stuff
ctx.addListener("org.springframework.web.context.ContextLoaderListener");
//enable web socket support
final WebSocketAddOn addon = new WebSocketAddOn();
for (NetworkListener listener : server.getListeners()) {
listener.registerAddOn(addon);
//if false, local files (html, etc.) can be modified without restarting the server
//#todo experiment with this setting in production vs development
listener.getFileCache().setEnabled(false);
}
//add jersey servlet support
/*ServletRegistration jerseyServletRegistration = ctx.addServlet("JerseyServlet", new ServletContainer());
jerseyServletRegistration.setInitParameter("com.sun.jersey.config.property.packages", "come.fettergroup.production.queue.resources");
jerseyServletRegistration.setLoadOnStartup(1);
jerseyServletRegistration.addMapping("/api/*");*/
//add atmosphere servlet support
AtmosphereServlet atmosphereServlet = new AtmosphereServlet();
AtmosphereFramework f = atmosphereServlet.framework();
ReflectorServletProcessor r = new ReflectorServletProcessor();
r.setServletClassName("com.sun.jersey.spi.spring.container.servlet.SpringServlet");
f.addAtmosphereHandler("/socket/*", r);
ServletRegistration atmosphereServletRegistration = ctx.addServlet("AtmosphereServlet", atmosphereServlet);
atmosphereServletRegistration.setInitParameter("org.atmosphere.websocket.messageContentType", "application/json");
atmosphereServletRegistration.setInitParameter("com.sun.jersey.api.json.POJOMappingFeature", "true");
atmosphereServletRegistration.setLoadOnStartup(1);
ctx.deploy(server);
//serve static assets
StaticHttpHandler staticHttpHandler = new StaticHttpHandler("src/main/web");
server.getServerConfiguration().addHttpHandler(staticHttpHandler, "/");
//start the production process
Production.init();
server.start();
System.in.read();
server.stop();
}
Haven't tried this yet but the org.springframework.web.context.ContextLoaderListener class needs to be configured to use an annotation scanning application context. This is done via context parameters.
So in a web.xml file, you would do something like this:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.yourbasepackage</param-value>
</context-param>
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
For a standalone Jetty, you need to do something similar using the WebAppContext.setInitParameter() method.
ctx.setInitParameter("contextClass", "org.springframework.web.context.support.AnnotationConfigWebApplicationContext");
ctx.setInitParameter("contextConfigLocation", "com.yourbasepackage");

Spring and returning protected resources

I have a pretty standard Spring 3.0.7 web app
The structure is like this
WebContent/
resources/
myStaticConent/
WEB-INF/
views/
myProtectedContent/
I am using the <mvc:resources> configuration for the static content and my controllers get views using the InternalViewResolver from WEB-INF/views
Now I have a requirement to return non-JSP content ( JPGs,PNGs,HTML,etc ) from a protected directory in WEB-INF
So a user might enter a URL like http:myWebApp/myProtectedContent and hit my protected content controller.
#Controller
public class HelloWorldController {
#RequestMapping(value="/myProtectedContent")
public String index() {
return "myjpg.jpg";
}
}
Essentially I want to conditionally serve a file just like I would a view. Anyone know how this can be done ?
I looked at some of the other methods here, Streaming using Inputstream seems overkill for files that are essentially static. Can I register another "view" type ? I need this to appear l( from the web browser side ) like a standard http request response ( like the current view implementation).
I would really like to avoid inventing my own file handling methods unless there is some reason why using the file access methods are better then Springs "other" view resolvers like ResourceBundleResolver
So the requirement is
Conditionally respond to a http request with variable file type (jpg,png,html) from inside WEB-INF without wrapping in a jsp or having the file interpreted by the JSTL view. The names of the files are known and static. The controller will determine the file name based on its own business logic.
You can reproduce the behavior of the underlying implementation of <mvc:resources/> which is org.springframework.web.servlet.resource.ResourceHttpRequestHandler, which essentially streams out the content of the static files - You can like ResourceHttpRequestHandler, extend from org.springframework.web.servlet.support.WebContentGenerator which has extensive support for sending last-modified and caching related headers, and finally to stream the content also there is a utility that Spring provides:
org.springframework.util.FileCopyUtils.copy(resource.getInputStream(), response.getOutputStream());
Updated:
#Controller
public class HelloWorldController implements ApplicationContextAware {
ApplicatonContext ctx = ...;
#RequestMapping(value="/myProtectedContent")
public void index(HttpServletRequest req, HttpServletResponse res) {
Resource resource = ctx.getResource("classpath:staticpath/myjpg.jpg");
FileCopyUtils.copy(resource.getInputStream(), response.getOutputStream());
}
}
Something you can do is to map a new servlet to the path you want to be protected and handle the request the way you want.
For example, in web.xml:
<servlet>
<servlet-name>protServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/protServlet-context.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>protServlet</servlet-name>
<url-pattern>/myProtectedContent</url-pattern>
</servlet-mapping>
This way, you map a new servlet (DispatcherServlet) for URLs that are protected content.
The load-on-startup value equals 2 is due if you already have a DispatcherServlet with this field value equals 1.

Doing integration testing on Oracle ADF application

I have an ADF application which running on my server. I was trying to run some integration test cases on it. I used to use apache cactus framework to run testing on normal web applications. My test cases would extend CactusStrutsTestCase and will be run.
I tried to approach, ADF application with same concept. But I am getting connection refused error
java.net.ConnectException: Connection refused: connect
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
So my question is that , is it possible to do testing in ADF application with a ServletTestcase which is part of Cactus framework ?
Thanks
Jijoy
What you are doing is possible. I know, because I've done it.
First off, ditch genuine Apache Cactus. It's not being supported anymore. You want to download JSFUnit and use that instead. It makes use of Apache Cactus but is still being actively maintained.
I suggest you create your own test case which extends ServletTestCase instead of using ServletTestCase directly.
public class EJBTestCase extends ServletTestCase {
protected InitialContext context;
public static final String userId = "demouser";
public EJBTestCase(String string) {
super(string);
}
private InitialContext getInitialContext() throws NamingException {
Hashtable env = new Hashtable();
env.put(Context.SECURITY_PRINCIPAL, "username");
env.put(Context.SECURITY_CREDENTIALS, "password");
return new InitialContext(env);
}
public void setUp() throws Exception {
super.setUp();
context = getInitialContext();
}
public void tearDown() throws Exception {
super.tearDown();
context.close();
}
public EJBTestCase() {
super();
}
}
Next, you need to setup your web.xml file:
<filter>
<filter-name>JSFUnitFilter</filter-name>
<filter-class>org.jboss.jsfunit.framework.JSFUnitFilter</filter-class>
</filter>
...
<filter-mapping>
<filter-name>JSFUnitFilter</filter-name>
<servlet-name>ServletTestRunner</servlet-name>
</filter-mapping>
<filter-mapping>
<filter-name>JSFUnitFilter</filter-name>
<servlet-name>ServletRedirector</servlet-name>
</filter-mapping>
...
<servlet>
<servlet-name>ServletRedirector</servlet-name>
<servlet-class>org.jboss.jsfunit.framework.JSFUnitServletRedirector</servlet-class>
</servlet>
<servlet>
<servlet-name>ServletTestRunner</servlet-name>
<servlet-class>org.apache.cactus.server.runner.ServletTestRunner</servlet-class>
</servlet>
...
<servlet-mapping>
<servlet-name>ServletRedirector</servlet-name>
<url-pattern>/ServletRedirector</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ServletTestRunner</servlet-name>
<url-pattern>/ServletTestRunner</url-pattern>
</servlet-mapping>
Finally, when you run your test cases you must pass in the cactus.contextURL parameter.
-Dcactus.contextURL=http://127.0.0.1:7101/MyApp
I assume you are using JDeveloper. You can then set this under Project Properties > Run/Debug/Profile -> Edit > Launch Settings -> Java Options.

Categories