Access to file to files a file in tomcat's conf folder - file

I would like to know if it's possible to access a file putted on the conf folder of tomcat.
Typically i will put configuration for multiple webapp , outside of the wars, in this file.
I want to use the classpath to be independent from the file system.
I used the lib folder in the past. It work great.
But it's a bit of a none sense using the lib folder to put conf file.
Can someone help me on this one?

I have seen lots of bad ways people do configuration in webapps that either makes it not really config (you have to do redeploy/release when you change config) or you have very little flexibility.
How I approach the problem is to use Spring for property placeholder but often times you need to bootstrap Spring or whatever you MVC stack before it loads with a property that says where to load config. I use a listener for that:
package com.evocatus.util;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class SimpleContextListenerConfig /*extend ResourceBundle */ implements ServletContextListener{
private ServletContext servletContext;
#Override
public void contextInitialized(ServletContextEvent sce) {
servletContext = sce.getServletContext();
servletContext.setAttribute(getClass().getCanonicalName(), this);
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
}
public static String getProperty(ServletContext sc, String propName, String defaultValue) {
SimpleContextListenerConfig config = getConfig(sc);
return config.getProperty(propName, defaultValue);
}
public static SimpleContextListenerConfig getConfig(ServletContext sc) {
SimpleContextListenerConfig config =
(SimpleContextListenerConfig) sc.getAttribute(SimpleContextListenerConfig.class.getCanonicalName());
return config;
}
public String getProperty(String propName, String defaultValue)
{
/*
* TODO cache properties
*/
String property = null;
if (property == null)
property = servletContext.getInitParameter(propName);
if (property == null)
System.getProperty(propName, null);
//TODO Get From resource bundle
if (property == null)
property = defaultValue;
return property;
}
}
https://gist.github.com/1083089
The properties will be pulled first from the servlet context, then system properties thus allowing you to override for certain webapps.
You can change the config for certian webapp either by changing web.xml (not recommended) or by creating a context.xml
You can use the static methods to get the config:
public static SimpleContextListenerConfig getConfig(ServletContext sc);

Related

Hystrix Javanica : Call always returning result from fallback method.(java web app without spring)

I am trying to integrate Hystrix javanica into my existing java EJB web application and facing 2 issues with running it.
When I try to invoke following service it always returns response from fallback method and I see that the Throwable object in fallback method has "com.netflix.hystrix.exception.HystrixTimeoutException" exception.
Each time this service is triggered, HystrixCommad and fallback methods are called multiple times around 50 times.
Can anyone suggest me with any inputs? Am I missing any configuration?
I am including following libraries in my project.
project libraries
I have setup my aspect file as follows:
<aspectj>
<weaver options="-verbose -showWeaveInfo"></weaver>
<aspects>
<aspect name="com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect"/>
</aspects>
</aspectj>
Here is my config.properties file in META-INF/config.properties
hystrix.command.default.execution.timeout.enabled=false
Here is my rest service file
#Path("/hystrix")
public class HystrixService {
#GET
#Path("clusterName")
#Produces({ MediaType.APPLICATION_JSON })
public Response getClusterName(#QueryParam("id") int id) {
ClusterCmdBean clusterCmdBean = new ClusterCmdBean();
String result = clusterCmdBean.getClusterNameForId(id);
return Response.ok(result).build();
}
}
Here is my bean class
public class ClusterCmdBean {
#HystrixCommand(groupKey = "ClusterCmdBeanGroup", commandKey = "getClusterNameForId", fallbackMethod = "defaultClusterName")
public String getClusterNameForId(int id) {
if (id > 0) {
return "cluster"+id;
} else {
throw new RuntimeException("command failed");
}
}
public String defaultClusterName(int id, Throwable e) {
return "No cluster - returned from fallback:" + e.getMessage();
}
}
Thanks for the help.
If you want to ensure you are setting the property, you can do that explicitly in the circuit annotation itself:
#HystrixCommand(commandProperties = {
#HystrixProperty(name = "execution.timeout.enabled", value = "false")
})
I would only recommend this for debugging purposes though.
Something that jumps out to me is that Javanica uses AspectJ AOP, which I have never seen work with new MyBean() before. I've always have to use #Autowired with Spring or similar to allow proxying. This could well just be something that is new to me though.
If you set a breakpoint inside the getClusterNameForId can you see in the stack trace that its being called via reflection (which it should be AFAIK)?
Note you can remove commandKey as this will default to the method name. Personally I would also remove groupKey and let it default to the class name.

Spring rest application and exception localization

I am developing a spring boot app with restful services and angularjs as front end. The application must support multiple languages. One of the things I am having problem is the business exceptions thrown from my services. E.g. I have a book service which may throw an exception like this
if (book == null) {
throw new ServiceException("The book you are looking for no longer exist");
}
What is the best approach to localize them?
You have to use #RestControllerAdvice to seprate your exception handling logic from your business code. As per #ControllerAdvice doc, the methods defined in the class annotated as #ControllerAdvice apply globally to all Controllers. #RestControllerAdvice is just a convenience class equal to (#RestControllerAdvice = #ControllerAdvice + #ResponseBody). Please check below class:
#RestControllerAdvice
public class GenericExceptionHandler {
#Autowired
private MessageSource messageSource;
#ExceptionHandler(ServiceException.class)
public ResponseEntity<ErrorResponse> handle(ServiceException.class e, Locale locale) {
String errorMessage = messageSource.getMessage(
"error.message", new Object[]{},locale);
ErrorResponse error = new ErrorResponse();
error.setErrorCode(HttpStatus.BAD_REQUEST.value());
error.setMessage(errorMessage);
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}
}
// other Custom Exception handlers
Your ErrorResponse is normal javabean as below:
public class ErrorResponse{
private int errorCode;
private String message;
//getter and setter
}
And you should have MessageSource configured in your configuration to read the locale specific error messages as below:
#Configuration
public class MessageConfig {
#Bean
public MessageSource messageSource() {
ResourceBundleMessageSource source = new ResourceBundleMessageSource();
source.setBasename("i18n/messages");
source.setUseCodeAsDefaultMessage(true);
return source;
}
}
I would like to suggest use of #ControllerAdvice and #ExceptionHandler.
Also you can use #RestControllerAdvice, find example here

Nancy fails to find static content in custom convention

I've set up a Nancy bootstrapper to serve static content from a non-default directory path (it's self hosted Nancy).
Strangely, the following works for the custom View location convention but not either of the js or css static content conventions (and yes, both files and folders exist at these locations!). My attempts at trying to resolve this are further compounded as I haven't figured out how to log errors which occur when static content is not found.
using System;
using System.IO;
using Nancy;
using Nancy.Conventions;
using Nancy.Bootstrapper;
using Nancy.TinyIoc;
namespace MyApp
{
public class ApplicationBootstrapper : DefaultNancyBootstrapper
{
private const string RELATIVE_PATH_TO_SOURCE = #"../static/MyApp/";
protected override void ConfigureConventions(NancyConventions nancyConventions)
{
nancyConventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("js", string.Concat(RELATIVE_PATH_TO_SOURCE, "Scripts/")));
nancyConventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("css", string.Concat(RELATIVE_PATH_TO_SOURCE, "Content/")));
this.Conventions.ViewLocationConventions.Add((viewName, model, context) =>
{
return string.Concat(RELATIVE_PATH_TO_SOURCE, "Views/", viewName);
});
this.Conventions.ViewLocationConventions.Add((viewName, model, context) =>
{
return string.Concat(RELATIVE_PATH_TO_SOURCE, "Views/", context.ModuleName, "/", viewName);
});
base.ConfigureConventions(nancyConventions);
}
protected override IRootPathProvider RootPathProvider
{
get
{
return new MyRootPathProvider();
}
}
protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
{
pipelines.OnError += (ctx, ex) =>
{
Console.WriteLine("RootPath : {0}", DebugRootPathProvider.RootPath);
Console.WriteLine("Unhandled error on request: {0} : {1}", ctx.Request.Url, ex.Message); //HACK
Console.WriteLine(ex.StackTrace); //HACK poor man's logging
return null;
};
}
}
public class MyRootPathProvider : IRootPathProvider
{
public static readonly string RootPath;
static MyRootPathProvider()
{
RootPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
}
public string GetRootPath()
{
return RootPath;
}
}
}
The output from Chrome and ProcMon is as follows:
How should I:
Log errors occurring with not found js and css files?
Resolve the 404 errors with the static file conventions?
Instead of logging you can use sysinternals process monitor and look for what files the nancy process (exe or IIS worker process) are attempting to read.
I had problems with serving static files (in my case js files) in a self host environment as well. They were not recognized at all, not even in the default "Content" folder. My solution: I installed the Microsoft StaticFiles NuGet Package.
In the startup class, register a static files folder like this:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseStaticFiles("/Scripts");
app.MapSignalR();
app.UseNancy();
}
}
This way, all files and subfolders in the "Scripts" folder are served as static files. There is also an overload of the UseStaticFiles() function that lets you map a physical path to a virtual path.
Important here: the call to UseNancy() has to be the very last, otherwise everything after it won't work. I also tried to combine it with SignalR, as you can see above, and there the UseNancy() call had to be at the end as well.

Making a Settings.txt File - How to load settings the right way?

I have an app I'm working on and it should save and load settings through an XML file (named Settings.txt)
Now, here's the code I use:
public class Settings
{
public bool Selected_64Bit { get; set; }
public bool Supported_64Bit { get; set; }
public bool FirstTime { get; set; }
}
static void SaveSettings(Settings settings)
{
var serializer = new XmlSerializer(typeof(Settings));
using (var stream = File.OpenWrite("settings.txt"))
{
serializer.Serialize(stream, settings);
}
}
static Settings LoadSettings()
{
if (!File.Exists("settings.txt"))
return new Settings();
var serializer = new XmlSerializer(typeof(Settings));
using (var stream = File.OpenRead("settings.txt"))
{
return (Settings)serializer.Deserialize(stream);
}
}
Now, I need to load the settings into a new Settings().
I found out that doing:
Settings [VAR] = new Settings()
will make a new Settings() with all false, but I want to LOAD the saved settings..
I'm confused and can't explain this to myself...
The final product should:
Check if settings.txt exists
If it does - LOAD SETTINGS into a new Settings called Setting (in my case).
If it doesn't - Make new settings and then save them.
I hope someone understood and can help me.
BTW - I'm not so good in C#, and I don't get the get\set thingy at all, as of return and other methods like that.. I know the basics and I'll be happy if I won't need more complicated techniques.
And if I must use more complicated techniques - please explain them deeply because I DO NOT KNOW.
As you have it set up, you'd need to do:
Settings mySettings = Settings.LoadSettings();
This will run your static LoadSettings method and return a Settings object.
As Matt already wrote
Settings mySettings = Settings.LoadSettings();
will do the job.
If you have a application you could use its settings as well. You get that settings by Properties.Settings.Default and in your project settings you can define some properties.

Example of testing a RPC call using GWT-TestCase with GAE

How is that for a lot of acronyms!
I am having trouble testing GWT's RPC mechanism using GWT's GWTTestCase. I created a class for testing using the junitCreator tool included with GWT. I am attempting to test using the built in Google App Engine using the created "hosted mode" testing profile created by junitCreator. When I run the test, I keep getting errors saying things like
Starting HTTP on port 0
HTTP listening on port 49569
The development shell servlet received a request for 'greet' in module 'com.google.gwt.sample.stockwatcher.StockWatcher.JUnit.gwt.xml'
[WARN] Resource not found: greet; (could a file be missing from the public path or a <servlet> tag misconfigured in module com.google.gwt.sample.stockwatcher.StockWatcher.JUnit.gwt.xml ?)
com.google.gwt.user.client.rpc.StatusCodeException: Cannot find resource 'greet' in the public path of module 'com.google.gwt.sample.stockwatcher.StockWatcher.JUnit'
I hope that someone somewhere has successfully run junit test (using GWTTestCase or just plain TestCase) that will allow for the testing of gwt RPC. If this is the case, could you please mention the steps you took, or better yet, just post code that works. Thanks.
SyncProxy allows you to make GWT RPC call from Java. So you can test your GWT RPC with regular Testcase (and faster than GwtTestcase)
See
http://www.gdevelop.com/w/blog/2010/01/10/testing-gwt-rpc-services/
http://www.gdevelop.com/w/blog/2010/03/13/invoke-gwt-rpc-services-deployed-on-google-app-engine/
I got this working. This answer assume's you're using Gradle, but this could easily be adopted to run from ant. First, you'll have to make sure that you separate your GWT tests from your regular JUnit tests. I created 'tests/standalone' for the regular tests, and 'tests/gwt' for my GWT tests. I still get 1 single HTML report in the end that has all of the info.
Next, you need to make sure JUnit is part of your ant classpath, as described here:
http://gradle.1045684.n5.nabble.com/Calling-ant-test-target-fails-with-junit-classpath-issue-newbie-td4385167.html
Then, use something similar to this to compile your GWT tests and run them:
task gwtTestCompile(dependsOn: [compileJava]) << {
ant.echo("Copy the test sources in so they're part of the source...");
copy {
from "tests/gwt"
into "$buildDir/src"
}
gwtTestBuildDir = "$buildDir/classes/test-gwt";
(new File(gwtTestBuildDir)).mkdirs()
(new File("$buildDir/test-results")).mkdirs()
ant.echo("Compile the tests...");
ant.javac(srcdir: "tests/gwt", destdir: gwtTestBuildDir) {
classpath {
pathElement(location: "$buildDir/src")
pathElement(location: "$buildDir/classes/main")
pathElement(path: configurations.runtime.asPath)
pathElement(path: configurations.testCompile.asPath)
pathElement(path: configurations.gwt.asPath)
pathElement(path: configurations.gwtSources.asPath)
}
}
ant.echo("Run the tests...");
ant.junit(haltonfailure: "true", fork: "true") {
classpath {
pathElement(location: "$buildDir/src")
pathElement(location: "$buildDir/classes/main")
pathElement(location: gwtTestBuildDir)
pathElement(path: configurations.runtime.asPath)
pathElement(path: configurations.testCompile.asPath)
pathElement(path: configurations.gwt.asPath)
pathElement(path: configurations.gwtSources.asPath)
}
jvmarg(value: "-Xmx512m")
jvmarg(line: "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005")
test(name: "com.onlyinsight.client.LoginTest", todir: "$buildDir/test-results")
formatter(type: "xml")
}
}
test.dependsOn(gwtTestCompile);
Finally, here's a simple GWT test:
public class LoginTest extends GWTTestCase
{
public String getModuleName()
{
return "com.onlyinsight.ConfModule";
}
public void testRealUserLogin()
{
UserServiceAsync userService = UserService.App.getInstance();
userService.login("a", "a", new AsyncCallback<User>()
{
public void onFailure(Throwable caught)
{
throw new RuntimeException("Unexpected Exception occurred.", caught);
}
public void onSuccess(User user)
{
assertEquals("a", user.getUserName());
assertEquals("a", user.getPassword());
assertEquals(UserRole.Administrator, user.getRole());
assertEquals("Test", user.getFirstName());
assertEquals("User", user.getLastName());
assertEquals("canada#onlyinsight.com", user.getEmail());
// Okay, now this test case can finish.
finishTest();
}
});
// Tell JUnit not to quit the test, so it allows the asynchronous method above to run.
delayTestFinish(10 * 1000);
}
}
If your RPC instance doesn't have a handy getInstance() method, then add one:
public interface UserService extends RemoteService {
public User login(String username, String password) throws NotLoggedInException;
public String getLoginURL(OAuthProviderEnum provider) throws NotLoggedInException;
public User loginWithOAuth(OAuthProviderEnum provider, String email, String authToken) throws NotLoggedInException;
/**
* Utility/Convenience class.
* Use UserService.App.getInstance() to access static instance of UserServiceAsync
*/
public static class App {
private static final UserServiceAsync ourInstance = (UserServiceAsync) GWT.create(UserService.class);
public static UserServiceAsync getInstance()
{
return ourInstance;
}
}
}
I hope that helps.

Resources