Stripes allows you to validate your form input values using the #Validate annotation on your member variables. Does anyone have any experience testing these annotations directly. I could do this by testing the validation errors that come back from the ActionBean, but this seems a little long winded and I would like a more direct method of testing if an input value is valid.
I'm not that familiar with the innards of the Framework yet, and I was hoping someone could give me some direction on where to start. TIA.
One method I've used is Stripes' built in MockRoundtrip. It is useful for simulating a complete test of an action bean event outside the container.
Example from the documentation:
MockServletContext context = ...;
MockRoundtrip trip = new MockRoundtrip(context, CalculatorActionBean.class);
trip.setParameter("numberOne", "2");
trip.setParameter("numberTwo", "2");
trip.execute();
CalculatorActionBean bean = trip.getActionBean(CalculatorActionBean.class);
Assert.assertEquals(bean.getResult(), 4, "two plus two should equal four");
Assert.assertEquals(trip.getDestination(), ""/quickstart/index.jsp");
Additionally, you could use trip.getValidationErrors() and assert that your error is in there.
Related
I am making an address book application and I am brand new to aspectj and I am trying to use a variable int inside the aspect but eclipse is saying it "Cannot be resolved to a variable".
What do I need to do to use the variable? Thanks for any help you can give me.
Aspect
before(): execution(* *.deleteAddress(int <--PARAMETER I WANT TO USE))
{
fileServices.addXMLToFile(fileServices.makeXML(FileServices.map.get(WHERE I WANT TO PUT THE PARAMETER)), FileServices.ProductionFileName);
}
Here is the code if that will help
public void deleteAddress(int keyNumber) throws Exception
{
Address oldAddress = map.get(keyNumber);
map.remove(keyNumber);
addXMLToFile(makeXML(oldAddress), BackupFileName);
}
You need to use args() in order to bind positional parameters to advice method arguments.
The Spring manual explains that for Spring AOP (which is technically different, but shares a subset of syntax with AspectJ), but they syntax which is rather unusual for beginners, referring to pointcuts defined in in a different class.
Better read the AspectJ manual which also explains it. I just noticed you use native AspectJ syntax anyway, which means Spring AOP is not your topic. Let me just leave the reference in my answer for Spring AOP users.
In your case the answer - now in native AspectJ syntax again - would be (untested, just texting freestyle):
before(int keyNumber) : execution(* *.deleteAddress(int)) && args(keyNumber) {
fileServices.addXMLToFile(
fileServices.makeXML(
FileServices.map.get(keyNumber)
),
FileServices.ProductionFileName
);
}
I'm using the aggregator of spring integration in my app.
I'm using cucumber to test the flow, and I want to make sure that the aggregator release
strategy is executed by the right parameters. I have 2 params for that strategy:
timeout, and size.
I would like to know if there is a way to load those parameters dynamically during the steps?
So far I'm lost about how to make it work.
Thanks,
Thank you Artem,
I used the directFieldAccessor and I'm trying to get the release-strategy-expression and group-timeout attributes from the aggregator, but the problem is that I can't access those fields:
public void setAggregatorConfiguration(String aggregatorName, int aggregationThreshold, long aggregationTimeout) {
EventDrivenConsumer aggregator = getAggregator(aggregatorName);
DirectFieldAccessor directFieldAccessor = new DirectFieldAccessor(aggregator);
directFieldAccessor.setPropertyValue("group-timeout", aggregationTimeout);
}
I have 2 params for that strategy: timeout, and size
Well, I guess you use TimeoutCountSequenceSizeReleaseStrategy. As we see those params are final in that class and they really can't be changed at runtime just with setters.
There is only one way to change such values at runtime - using DirectFieldAccessor.
However if you share more info about your use-case and config and unit test as well, we might find some other way to help you.
I've edited your post to add your code. No, you have to use the real property name, so it should be groupTimeoutExpression, not group-timeout. From other side there is a public setter on the matter: AbstractCorrelatingMessageHandler.setGroupTimeoutExpression(Expression groupTimeoutExpression).
From other side you go a bit wrong way: any MessageHandler component (<aggregator>, <service-activator>) provides several component. Right, the root of them is a AbstractEndpoint (the parent of EventDrivenConsumer). But all of your desired properties are to the AggregatingMessageHandler, which can get from BeanFactory using its alias - aggregatorName + ".handler".
release-strategy-expression is property of ExpressionEvaluatingReleaseStrategy, which you can change using DirectFieldAccessor on the AggregatingMessageHandler:
AggregatingMessageHandler handler = beanFactory.getBean(aggregatorName + ".handler", AggregatingMessageHandler.class);
DirectFieldAccessor directFieldAccessor = new DirectFieldAccessor(handler);
ReleaseStrategy releaseStrategy = (ReleaseStrategy) directFieldAccessor.getPropertyValue("releaseStrategy");
DirectFieldAccessor dfa = new DirectFieldAccessor(releaseStrategy);
dfa.setPropertyValue("expression", ...);
Anyway, it isn't clear, why you need such a perversion...
We all know, that Spring MVC integrate well with Hibernate Validator and JSR-303 in general. But Hibernate Validator, as someone said, is something for Bean Validation only, which means that more complex validations should be pushed to the data layer. Examples of such validations: business key uniqueness, intra-records dependence (which is usually something pointing at DB design problems, but we all live in an imperfect world). Even simple validations like string field length may be driven by some DB value, which makes Hibernate Validator unusable.
So my question is, is there something Spring or Hibernate or JSR offers to perform such complex validations? Is there some established pattern or technology piece to perform such a validation in a standard Controller-Service-Repository setup based on Spring and Hibernate?
UPDATE: Let me be more specific. For example, there's a form which sends an AJAX save request to the controller's save method. If some validation error occurs -- either simple or "complex" -- we should get back to the browser with some json indicating a problematic field and associated error. For simple errors I can extract the field (if any) and error message from BindingResult. What infrastructure (maybe specific, not ad-hoc exceptions?) would you propose for "complex" errors? Using exception handler doesn't seem like a good idea to me, because separating single process of validation between save method and #ExceptionHandler makes things intricate. Currently I use some ad-hoc exception (like, ValidationException):
public #ResponseBody Result save(#Valid Entity entity, BindingResult errors) {
Result r = new Result();
if (errors.hasErrors()) {
r.setStatus(Result.VALIDATION_ERROR);
// ...
} else {
try {
dao.save(entity);
r.setStatus(Result.SUCCESS);
} except (ValidationException e) {
r.setStatus(Result.VALIDATION_ERROR);
r.setText(e.getMessage());
}
}
return r;
}
Can you offer some more optimal approach?
Yes, there is the good old established Java pattern of Exception throwing.
Spring MVC integrates it pretty well (for code examples, you can directly skip to the second part of my answer).
What you call "complex validations" are in fact exceptions : business key unicity error, low layer or DB errors, etc.
Reminder : what is validation in Spring MVC ?
Validation should happen on the presentation layer. It is basically about validating submitted form fields.
We could classify them into two kinds :
1) Light validation (with JSR-303/Hibernate validation) : checking that a submitted field has a given #Size/#Length, that it is #NotNull or #NotEmpty/#NotBlank, checking that it has an #Email format, etc.
2) Heavy validation, or complex validation are more about particular cases of field validations, such as cross-field validation :
Example 1 : The form has fieldA, fieldB and fieldC. Individually, each field can be empty, but at least one of them must not be empty.
Example 2 : if userAge field has a value under 18, responsibleUser field must not be null and responsibleUser's age must be over 21.
These validations can be implemented with Spring Validator implementations, or custom annotations/constraints.
Now I understand that with all these validation facilites, plus the fact that Spring is not intrusive at all and lets you do anything you want (for better or for worse), one can be tempted to use the "validation hammer" for anything vaguely related to error handling.
And it would work : with validation only, you check every possible problem in your validators/annotations (and hardly throw any exception in lower layers). It is bad, because you pray that you thought about all the cases. You don't leverage Java exceptions that would allow you to simplify your logic and reduce the chance of making a mistake by forgetting to check that something had an error.
So in the Spring MVC world, one should not mistake validation (that is to say, UI validation) for lower layer exceptions, such has Service exceptions or DB exceptions (key unicity, etc.).
How to handle exceptions in Spring MVC in a handy way ?
Some people think "Oh god, so in my controller I would have to check all possible checked exceptions one by one, and think about a message error for each of them ? NO WAY !". I am one of those people. :-)
For most of the cases, just use some generic checked exception class that all your exceptions would extend. Then simply handle it in your Spring MVC controller with #ExceptionHandler and a generic error message.
Code example :
public class MyAppTechnicalException extends Exception { ... }
and
#Controller
public class MyController {
...
#RequestMapping(...)
public void createMyObject(...) throws MyAppTechnicalException {
...
someServiceThanCanThrowMyAppTechnicalException.create(...);
...
}
...
#ExceptionHandler(MyAppTechnicalException.class)
public String handleMyAppTechnicalException(MyAppTechnicalException e, Model model) {
// Compute your generic error message/code with e.
// Or just use a generic error/code, in which case you can remove e from the parameters
String genericErrorMessage = "Some technical exception has occured blah blah blah" ;
// There are many other ways to pass an error to the view, but you get the idea
model.addAttribute("myErrors", genericErrorMessage);
return "myView";
}
}
Simple, quick, easy and clean !
For those times when you need to display error messages for some specific exceptions, or when you cannot have a generic top-level exception because of a poorly designed legacy system you cannot modify, just add other #ExceptionHandlers.
Another trick : for less cluttered code, you can process multiple exceptions with
#ExceptionHandler({MyException1.class, MyException2.class, ...})
public String yourMethod(Exception e, Model model) {
...
}
Bottom line : when to use validation ? when to use exceptions ?
Errors from the UI = validation = validation facilities (JSR-303 annotations, custom annotations, Spring validator)
Errors from lower layers = exceptions
When I say "Errors from the UI", I mean "the user entered something wrong in his form".
References :
Passing errors back to the view from the service layer
Very informative blog post about bean validation
Thank you all for your help. A number of you posted (as I should have expected) answers indicating my whole approach was wrong, or that low-level code should never have to know whether or not it is running in a container. I would tend to agree. However, I'm dealing with a complex legacy application and do not have the option of doing a major refactoring for the current problem.
Let me step back and ask the question the motivated my original question.
I have a legacy application running under JBoss, and have made some modifications to lower-level code. I have created a unit test for my modification. In order to run the test, I need to connect to a database.
The legacy code gets the data source this way:
(jndiName is a defined string)
Context ctx = new InitialContext();
DataSource dataSource = (DataSource) ctx.lookup(jndiName);
My problem is that when I run this code under unit test, the Context has no data sources defined. My solution to this was to try to see if I'm running under the application server and, if not, create the test DataSource and return it. If I am running under the app server, then I use the code above.
So, my real question is: What is the correct way to do this? Is there some approved way the unit test can set up the context to return the appropriate data source so that the code under test doesn't need to be aware of where it's running?
For Context: MY ORIGINAL QUESTION:
I have some Java code that needs to know whether or not it is running under JBoss. Is there a canonical way for code to tell whether it is running in a container?
My first approach was developed through experimention and consists of getting the initial context and testing that it can look up certain values.
private boolean isRunningUnderJBoss(Context ctx) {
boolean runningUnderJBoss = false;
try {
// The following invokes a naming exception when not running under
// JBoss.
ctx.getNameInNamespace();
// The URL packages must contain the string "jboss".
String urlPackages = (String) ctx.lookup("java.naming.factory.url.pkgs");
if ((urlPackages != null) && (urlPackages.toUpperCase().contains("JBOSS"))) {
runningUnderJBoss = true;
}
} catch (Exception e) {
// If we get there, we are not under JBoss
runningUnderJBoss = false;
}
return runningUnderJBoss;
}
Context ctx = new InitialContext();
if (isRunningUnderJboss(ctx)
{
.........
Now, this seems to work, but it feels like a hack. What is the "correct" way to do this? Ideally, I'd like a way that would work with a variety of application servers, not just JBoss.
The whole concept is back to front. Lower level code should not be doing this sort of testing. If you need a different implementation pass it down at a relevant point.
Some combination of Dependency Injection (whether through Spring, config files, or program arguments) and the Factory Pattern would usually work best.
As an example I pass an argument to my Ant scripts that setup config files depending if the ear or war is going into a development, testing, or production environment.
The whole approach feels wrong headed to me. If your app needs to know which container it's running in you're doing something wrong.
When I use Spring I can move from Tomcat to WebLogic and back without changing anything. I'm sure that with proper configuration I could do the same trick with JBOSS as well. That's the goal I'd shoot for.
Perhaps something like this ( ugly but it may work )
private void isRunningOn( String thatServerName ) {
String uniqueClassName = getSpecialClassNameFor( thatServerName );
try {
Class.forName( uniqueClassName );
} catch ( ClassNotFoudException cnfe ) {
return false;
}
return true;
}
The getSpecialClassNameFor method would return a class that is unique for each Application Server ( and may return new class names when more apps servers are added )
Then you use it like:
if( isRunningOn("JBoss")) {
createJBossStrategy....etcetc
}
Context ctx = new InitialContext();
DataSource dataSource = (DataSource) ctx.lookup(jndiName);
Who constructs the InitialContext? Its construction must be outside the code that you are trying to test, or otherwise you won't be able to mock the context.
Since you said that you are working on a legacy application, first refactor the code so that you can easily dependency inject the context or data source to the class. Then you can more easily write tests for that class.
You can transition the legacy code by having two constructors, as in the below code, until you have refactored the code that constructs the class. This way you can more easily test Foo and you can keep the code that uses Foo unchanged. Then you can slowly refactor the code, so that the old constructor is completely removed and all dependencies are dependency injected.
public class Foo {
private final DataSource dataSource;
public Foo() { // production code calls this - no changes needed to callers
Context ctx = new InitialContext();
this.dataSource = (DataSource) ctx.lookup(jndiName);
}
public Foo(DataSource dataSource) { // test code calls this
this.dataSource = dataSource;
}
// methods that use dataSource
}
But before you start doing that refactoring, you should have some integration tests to cover your back. Otherwise you can't know whether even the simple refactorings, such as moving the DataSource lookup to the constructor, break something. Then when the code gets better, more testable, you can write unit tests. (By definition, if a test touches the file system, network or database, it is not a unit test - it is an integration test.)
The benefit of unit tests is that they run fast - hundreds or thousands per second - and are very focused to testing just one behaviour at a time. That makes it possible run then often (if you hesitate running all unit tests after changing one line, they run too slowly) so that you get quick feedback. And because they are very focused, you will know just by looking at the name of the failing test that exactly where in the production code the bug is.
The benefit of integration tests is that they make sure that all parts are plugged together correctly. That is also important, but you can not run them very often because things like touching the database make them very slow. But you should still run them at least once a day on your continuous integration server.
There are a couple of ways to tackle this problem. One is to pass a Context object to the class when it is under unit test. If you can't change the method signature, refactor the creation of the inital context to a protected method and test a subclass that returns the mocked context object by overriding the method. That can at least put the class under test so you can refactor to better alternatives from there.
The next option is to make database connections a factory that can tell if it is in a container or not, and do the appropriate thing in each case.
One thing to think about is - once you have this database connection out of the container, what are you going to do with it? It is easier, but it isn't quite a unit test if you have to carry the whole data access layer.
For further help in this direction of moving legacy code under unit test, I suggest you look at Michael Feather's Working Effectively with Legacy Code.
A clean way to do this would be to have lifecycle listeners configured in web.xml. These can set global flags if you want. For example, you could define a ServletContextListener in your web.xml and in the contextInitialized method, set a global flag that you're running inside a container. If the global flag is not set, then you are not running inside a container.
We use a standard SEAM setup here ... complete with the validation system that uses hibernate.
Basically what happens is a user enters a value into an html input and seam validates the value they entered using the hibernate validation.
Works fine for the most part except here's my problem: We need to record the results of validation on each field and I can't figure out a good way to do it ... ideally it would be done through communicating with the seam/hibernate validation system and just recording the validation results but as far as I can tell there isn't a way to do this?
Has anyone done anything like this in the past? There are a couple nasty work arounds but I'd prefer to do it cleanly.
Just a quick overview of the process that we have happening right now for context:
1) user enters field value
2) onblur value is set with ajax (a4j:support) at this point the validators fire and the div is re-rendered, if any validation errors occured they're now visible on the page
What I'd like to have happen at step2 is a 'ValidationListener' or something similar is called which would allow us to record the results of the validation.
Thanks if anyone is able to help :o
You should be able to do it by creating a Bean that has a method observing the org.jboss.seam.validationFailed event. That method can then do whatever logging you want.
#Name("validationObserver")
public class ValidationObserver() {
#Observer("org.jboss.seam.validationFailed")
public void validationFailed() {
//Do stuff
}
}
The validationFailed event doesn't pass any parameters so you'll have to interrogate the FacesMessages or possibly the Hibernate Validation framework itself if you want to record what the error was.
I you are only using Hibernate for validation, you can use the Hibernate ClassValidator in the validationFailed() method, as recommended by Damo.
Example:
public <T> InvalidValue[] validateWithHibernate(T object) {
ClassValidator<T> validator = new ClassValidator(object.getClass());
InvalidValue[] invalidValues = validator.getInvalidValues(object);
return invalidValues;
}