I have a servlet called Calculator. It reads the parameters left, right and op and returns by setting an attribute result in the response.
What is the easiest way to unit test this: basically I want to create an HttpServletRequest, set the parameters, and then checking the response - but how do I do that?
Here's the servlet code (it's small and silly on purpose):
public class Calculator extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
public Calculator() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Integer left = Integer.valueOf(request.getParameter("left"));
Integer right = Integer.valueOf(request.getParameter("right"));
Integer result = 0;
String op = request.getParameter("operator");
if ("add".equals(op)) result = this.opAdd(left, right);
if ("subtract".equals(op)) result = this.opSub(left, right);
if ("multiply".equals(op)) result = this.opMul(left, right);
if ("power".equals(op)) result = this.opPow(left, right);
if ("divide".equals(op)) result = this.opDiv(left, right);
if ("modulo".equals(op)) result = this.opMod(left, right);
request.setAttribute("result", result); // It'll be available as ${sum}.
request.getRequestDispatcher("index.jsp").forward(request, response);
}
}
...
}
Often, the important logic of a program is factored out into other classes, that are usable in a variety of contexts, instead of being tightly coupled to a Servlet Engine. This leaves the servlet itself as a simple adapter between the web and your application.
This makes the program easier to test, and easier to reuse in other contexts like a desktop or mobile app.
There are a few libraries out there that you can use. Are you using Spring http://www.springsource.org/ in your application? If so, there is one application for spring (spring-test) that contains MockHttpServletRequest. For example:
#Test
public void shouldReturnAValidaRedirectionMessage() {
MockHttpServletRequest request = new MockHttpServletRequest();
request.addParameter("op", "addition");
request.addParameter("left", "1");
request.addParameter("right", "5");
CalculatorServlet servlet = new CalculatorServlet();
Operation operation = servlet.getOperation(request);
assertNotNull(operation);
assertEquals(ADDITION, operation.getOperationType());
...
Check out ServletUnit. It's part of HttpUnit.
http://httpunit.sourceforge.net/doc/servletunit-intro.html
Can't say this is the best method to do so : but to unit test a simple servlet like that (one not using forwards, context etc..) what you could simply do is :
Create mock HttpServletReqeust and HttpServletResponse instances using any mocking library. Even simpler would be using RequestWrapper and ResponseWrapper classes (simple custom classes implemented by extending the HttpServletReqeust and HttpServletResponse classes).
On these mock (or custom) instances set certain properties - the parameters you want to test against in each test case - e.g. op=add for a addition unit test. If you are using custom classes, you can simply set them in an internal properties object. If you are using mocks, then settings expectations would do.
Create an instance of the servlet - new Calculator(), keeping the required libs in the class path. Now call the service method on this instance.
When the call returns, get the o/p from the response class and assert it. Since the response class is again a custom class or a mocked version, this should be easy.
For mocking, a simply starting point would be EasyMock or Mockito (my fav)
An example for the wrapper : http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/HttpServletRequestWrapper.html
HTH
Generally you should abstract your business logic from Servlet container details. You can mock ServletRequest using Spring test package, but it would be a bad idea to simulate Servlet container. So, you should either run system tests on a real container or move your logic from servlet into a separate bean and test it in isolation.
public class Calculator {
public Integer calculate(Integer left, Integer right, String op) {
Integer result = 0;
if ("add".equals(op)) result = this.opAdd(left, right);
if ("subtract".equals(op)) result = this.opSub(left, right);
if ("multiply".equals(op)) result = this.opMul(left, right);
if ("power".equals(op)) result = this.opPow(left, right);
if ("divide".equals(op)) result = this.opDiv(left, right);
if ("modulo".equals(op)) result = this.opMod(left, right);
return result;
}
}
public class CalculatorServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Integer left = Integer.valueOf(request.getParameter("left"));
Integer right = Integer.valueOf(request.getParameter("right"));
String op = request.getParameter("operator");
Integer result = calculator.calculate(left, right, op);
request.setAttribute("result", result); // It'll be available as ${sum}.
request.getRequestDispatcher("index.jsp").forward(request, response);
}
}
Related
We are using Guice in our project for DI. Currently we have some configurations(properties) that we load a t server startup from a file. These are then bound to all the components & used for all the requests.
But now, we have multiple property files & load them at startup. These configurations can be different per REST(Jersey) request as they depend on the input.
So, we need to bind these configurations dynamically for each request. I looked into Guice API for #RequestScoped, but did not find anything specificallyu helpful.
There are few questions similar to this, but no luck yet. Can you please help me with this.
I'm providing 2 ways of doing this and both are request scoped.
Using HttpServletRequest, for classes where you can Inject request object.
Using ThreadLocal, Generic way. It can be used in any class.
(NOTE: This method wouldn't work if your creating new threads in your code and want to access the value. In which case you'll have to pass the values through Objects to those threads)
I meant something like this:
public class RequestFilter implements ContainerRequestFilter {
#Context
private HttpServletRequest request;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
List listOfConfig = //load Config;
request.setAttribute("LOADED_CONFIG",listOfConfig);
// If you want to access this value at some place where Request object cannot be injected (like in service layers, etc.) Then use below ThreadLocals.
ThreadLocalWrapper.getInstance().get().add("adbc"); // In general add your config here, instead of abdc.
}
}
My ThreadLocalWrapper looks like this:
public class ThreadLocalWrapper {
private static ThreadLocal<List<String>> listOfStringLocals; // You can modify this to a list of Object or an Object by itself.
public static synchronized ThreadLocal<List<String>> getInstance() {
if (listOfStringLocals == null) {
listOfStringLocals = new ThreadLocal<List<String>>() {
#Override
protected List<String> initialValue() {
return new ArrayList<String>();
}
};
}
return listOfStringLocals;
}
}
To Access the value:
In Controller - Inject HttpServletRequest Object and do getAttribute() to get the value. Since HttpServletRequest Object is requestScoped, you can set the loaded config. into this and access it in your controller's using request Object again.
In Any other part of the code - If HttpServletRequest is not available then you can always use the ThreadLocal example shown. To access this value.
public class GuiceTransactionImpl implements GuiceTransaction {
private String value = "";
public GuiceTransactionImpl(String text) {
value = text;
}
#Override
public String returnSuccess() {
return value + " Thread Local Value " + ThreadLocalWrapper.getInstance().get();
}
}
First of all, I'm using command pattern with this interface:
public CommandResponse execute(HttpServletRequest req)
throws CommandException;
And this is my service method:
public void service(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
try {
Command cmd = lookupCommand(req.getParameter("cmd"));
CommandResponse next = cmd.execute(req, res);
CommandToken.set(req);
if (next != null) {
if (!req.getHeader("X-Requested-With").equals("XMLHttpRequest")) {
if (next.isRedirect()) {
redirect(next, res);
} else if (next.isForward()) {
forward(next, req, res);
}
} else {
ajaxCall(next, res);
}
}
} catch (CommandException e) {
res.sendError(HttpServletResponse.SC_BAD_REQUEST, e.toString());
}
}
As you can see my service method treats the logic of redirection and forward and my interface does not have access to the HttpServletResponse object. But for some actions of my servlet I need handle the response to add some content like a xml or a cookie. The more obvious way to achieve that is modify my interface to:
public CommandResponse execute(HttpServletRequest req, HttpServletResponse res)
throws CommandException;
Now the questions:
1-) In my opinion the solution above will break the elengacy and safety of the code since my actions now have access to the response and can redirect and forward, and even add content to the response and let the service method use sendRedirect wich we know would have no effect. Am I right? To solve that I do this:
public class CommandResponse {
private boolean redirect;
private boolean forward;
private String page;
private String contentType;
private String outContent;
private HashMap headers;
private List<Cookie> cookies;
...
public void mapToResponse(HttpServletResponse res) {
...
}
}
That is, I create a faked response and when I come back of the action execute method I map this faked response to the real http response (just if I have a forward or a ajax call).
2-) That is good? It makes sense? Should I not use it?
3-) There is a better way?
Thanks.
Why not just pass a strong buffer to capture any content that your subsequent chain may want to add? This way you are not confusing the responsibility of the components. Normally, httpresponse is expected to behave as any one would expect.
However, I would like to hear the reason behind this design.
Yes, there is a better way, take a look to Frontman, an elegant implementation of the Command pattern in servlets
http://www.bibeault.org/frontman/
(I'm not sure exactly how to phrase the title here, and because of that I'm not really sure how to go about searching for the answer either.)
I have a Java servlet engine that handles requests. Say we have a doGet() request:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//set up user data
//do whatever the user requested
SomeClass c = new SomeClass();
c.doSomething();
}
Now in doSomething(), I want to be able to access which user made the request. Right now I'm doing it by creating a Java object within the method and passing it to wherever I need it:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//set up user data
MyUserObj userObj = new MyUserObj();
userObj.setId('123');
//do whatever the user requested
SomeClass c = new SomeClass(userObj);
c.doSomething();
}
By doing this, I have access to the instance of MyUserObj, and it can be further passed along in the application as needed.
I know in ASP.NET MVC3 I can acheive this by storing items/attributes for the current thread like this: HttpContext.Current.Items.Add("myId", "123"). HttpContext is then available in other functions without explicitly having to pass around an object.
Is there a way in Java to set some variables per request (or even set the MyUserObject to be accessed later) without passing the object through as a parameter?
There isn't in the servlet API, but you can make your own pretty easily. (Some frameworks like spring-mvc, struts provide such functionality)
Just use a public static ThreadLocal to store and retrieve the object. You can even store the HttpServletRequest itself in the threadlocal and use its setAttribute()/getAttribute() methods, or you can store a threadlocal Map, to be agnostic of the servlet API. An important note is that you should clean the threadlocal after the request (with a Filter, for example).
Also note that passing the object as parameter is considered a better practice, because you usually pass it from the web layer to a service layer, which should not be dependent on web-related object, like a HttpContext.
If you decide that it is fine to store them in a thread-local, rather than passing them around:
public class RequestContext {
private static ThreadLocal<Map<Object, Object>> attributes = new ThreadLocal<>();
public static void initialize() {
attributes.set(new HashMap<Map<Object, Object>>());
}
public static void cleanup() {
attributes.set(null);
}
public static <T> T getAttribute(Object key) {
return (T) attributes.get().get(key);
}
public static void setAttribute(Object key, Object value) {
attributes.get().put(key, value);
}
}
And a necessary filter:
#WebFilter(urlPatterns="/")
public class RequestContextFilter implements Filter {
public void doFilter(..) {
RequestContext.initialize();
try {
chain.doFilter(request, response);
} finally {
RequestContext.cleanup();
}
}
}
You can attach an object to the current request with setAttribute. This API is primarily used for internal routing, but it's safe to use for your own purposes too, as long as you use a proper namespace for your attribute names.
I have the following two classes and I am starting to see a pattern that even with my little Java background is screaming for a fix. Every new Object is going to require a set of Actions and the number of classes could grow out of hand. How do I refactor this into a generic DeleteAction class?
I know some of the answers will be use Hibernate, or JPA, or some Framework, but at the moment I can't utilize any of those tools. Oh, and our server only has jdk 1.4 (don't ask!). Thanks.
public class DeleteCommitmentAction implements ControllerAction {
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException {
CommitmentListDAO clDAO = new CommitmentListDAO();
CommitmentItemForm ciForm = new CommitmentItemForm(clDAO);
CommitmentItem commitmentItem = ciForm.deleteCommitmentItem(request);
RequestDispatcher view = request.getRequestDispatcher("views/commitmentView_v.jsp");
view.forward(request, response);
}
}
.
public class DeleteProgramAction implements ControllerAction {
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException {
ProgramDAO prgDAO = new ProgramDAO();
ProgramForm prgForm = new ProgramForm(prgDAO);
ProgramForm prg = prgForm.deleteProgram(request);
RequestDispatcher view = request.getRequestDispatcher("views/programView_v.jsp");
view.forward(request, response);
}
}
The approach that I think I need to take is to make interfaces. Starting with the DAO, I have created the following interface.
public interface GenericDao {
public void create(Object object, STKUser authenticatedUser) throws DAOException;
public void retreive(String id, STKUser authenticatedUser) throws DAOException;
public void update( final Object object, STKUser authenticatedUser) throws DAOException;
public void delete(String id, STKUser authenticatedUser) throws DAOException;
}
And then in my DeleteAction class I tried this
GenericDao gDAO = new GenericDao();
but Eclipse is stating "Cannot instantiate the type GenericDao" So now I am lost.
Update: Based on Péter Török's answer, here is what I have:
This is the servlet specific for handling operations on Commitment Items:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String schema = General_IO.getSchemaPath("TPQOT_463_COMMITMENT", request.getServerName());
CommitmentListDAO clDAO = new CommitmentListDAO();
CommitmentItemForm ciForm = new CommitmentItemForm(clDAO);
CommitmentItem commitmentItem = new CommitmentItem();
// I think this is the Application Controller Strategy
actionMap.put(null, new ListCommitmentsAction());
actionMap.put("list", new ListCommitmentsAction());
actionMap.put("view", new ViewCommitmentItemAction(schema));
//actionMap.put("delete", new DeleteCommitmentAction(schema));
// Change to the Generic DeleteAction and pass in the parameters
actionMap.put("delete", new DeleteAction(ciForm, commitmentItem, schema, "views/commitmentDeleteConfirm_v.jsp", "views/commitmentView_v.jsp" ));
// When happy with this approach, change other actions to the Generic Versions.
actionMap.put("sqlConfirmDelete", new DeleteCommitmentConfirmAction());
actionMap.put("edit", new EditCommitmentItemAction(schema));
actionMap.put("sqlUpdate", new UpdateCommitmentItemAction1(schema));
actionMap.put("new", new NewCommitmentFormAction(schema));
actionMap.put("sqlInsert", new InsertCommitmentItemAction1(schema));
String op = request.getParameter("method");
ControllerAction action = (ControllerAction) actionMap.get(op);
if (action != null) {
action.service(request, response);
} else {
String url = "views/errorMessage_v.jsp";
String errMessage = "Operation '" + op + "' not a valid for in '" + request.getServletPath() + "' !!";
request.setAttribute("message", errMessage);
request.getRequestDispatcher(url).forward(request, response);
}
}
And here is the Generic DeleteAction:
public class DeleteAction implements ControllerAction {
private Form form;
private Object obj;
private String schema = null;
private String xPage;
private String yPage;
public DeleteAction(Form form, Object item, String schema, String yPage, String xPage) {
this.form = form;
this.item = item; //passed in javabean??
this.schema = schema;
this.xPage = xPage;
this.yPage = yPage;
}
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
item = form.delete(request);
/* Database schema is described in xml files.
Hash maps of field names, sizes, and titles; foreign key names, titles,
lookup tables; and primary keys information are used to dynamically
build HTML forms in the views.
*/
HashMap test = ReadTableSchema.returnSchema(schema);
HashMap hshFields = (HashMap) test.get("hshFields");
HashMap hshForeignKeys = (HashMap) test.get("hshForeignKeys");
HashMap hshPrimaryKeys = (HashMap) test.get("hshPrimaryKeys");
request.setAttribute("hshFields", hshFields);
request.setAttribute("hshPrimaryKeys", hshPrimaryKeys);
request.setAttribute("hshForeignKeys", hshForeignKeys);
request.setAttribute("item", item);
request.setAttribute("form", form);
request.setAttribute("pageName", "Delete");
//Check for deletion authorization if successful forward to the confirmation page
if (form.isSucces()) {
request.setAttribute("message", "Please confirm permanent deletion of the data below.");
RequestDispatcher view = request.getRequestDispatcher(yPage);
view.forward(request, response);
} else {
// Not authorized to delete the data so just re-display
RequestDispatcher view = request.getRequestDispatcher(xPage);
view.forward(request, response);
}
}
}
then here is the interface (right now just for delete) that will be used by all forms.
public interface CRUD {
public Object delete(HttpServletRequest request);
}
You can't instantiate an interface, you need a concrete subclass for that. However, creating concrete subclasses just increases the number of classes, which you are trying to avoid. It is better to use composition instead of inheritance.
Namely, if you manage to make a common interface for the forms, and hide the actions deleteCommitmentItem, deleteProgram etc. behind one single method, you can parametrize your action instances with the required form (or a factory to provide this), e.g.:
public class GenericAction implements ControllerAction {
private Form form;
private String page;
GenericAction(Form form, String page) {
this.form = form;
this.page = page;
}
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException {
Item item = form.performDelete(request);
RequestDispatcher view = request.getRequestDispatcher(page);
view.forward(request, response);
}
}
...
CommitmentListDAO clDAO = new CommitmentListDAO();
CommitmentItemForm ciForm = new CommitmentItemForm(clDAO);
GenericAction deleteCommitmentAction = new GenericAction(ciForm, "views/commitmentView_v.jsp");
ProgramDAO prgDAO = new ProgramDAO();
ProgramForm prgForm = new ProgramForm(prgDAO);
GenericAction deleteProgramAction = new GenericAction(prgForm, "views/programView_v.jsp");
Thus you need no new classes for new kinds of actions, just instantiate GenericAction with different parameters.
It's clear by your naming that you already have implemented DAO objects (CommitmentListDAO, ProgramDAO). You should (probably) modify these classes to implement your new interface. Then your problem now becomes, how do you know which DAO to instantiate when you're in your generic delete action. Either that DAO should be passed into your action directly, or some other information on how to instantiate it (either a Class or factory) must be provided to your action.
GenericDAO is an interface, it cannot be instantiated directly. I don't know much Java, but every OOP language is pretty much the same. So what you need to do is create a concrete implementation of your interface (as a class) and then instantiate that instead. Something like this (sorry for the C# code but you get the idea):
public interface IGenericDAO {
void create(...);
}
and the implementation:
public class GenericDAO implements IGenericDAO {
public void create(...) {
/* implementation code */
}
}
Does that make sense?
One servlet per action is not unreasonable. Consider that if you have to do some action X, then you need to do X. Write a servlet to do X. It's that simple.
As you're noticing, this could lead to a lot of nearly identical servlets. That's ok because now you can use delegation (as Peter Torok recommends) or inheritance to move all the shared and abstracted code into one place. Which is better? Either is better than neither. You are 90% of the way to victory if you use one or both as appropriate.
I prefer a main servlet from which all others inherit. This allows me to wrap every service call in a consistent proper transaction in the base controller class. The subclasses never have to worry about it. This code shows the gist of it.
public class BaseControllerAction implements ControllerAction {
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException {
Connection conn = null;
try {
conn = getAConnection();
log.info("+++ top of "+getClass().getName());
conn.getTranaction().begin();
String dest = go(request, response, conn);
conn.getTransaction().commit();
RequestDispatcher view = request.getRequestDispatcher(dest);
view.forward(request, response);
} catch (Exception e) {
conn.getTransaction().rollback();
} finally {
conn.close();
log.info("--- Bottom of "+getClass().getName());
}
protected abstract String go(HttpServletRequest request, HttpServletResponse response, Transaction transaction) throws ServletException;
}
and now you can implement your servlet:
public class DeleteCommitmentAction extends BaseControllerAction {
protected String go(HttpServletRequest request, HttpServletResponse response, Connection conn) throws ServletException {
// Given what this method is supposed to do, it's very reasonable
// to refer to models and DAOs related to deleting commitments.
Long id = new Long(request.getParameter("id"));
CommitmentDAO.delete(conn, id);
return "views/commitmentView_v.jsp";
}
}
So now none of your servlets have to worry about transactions or opening and closing connections. They only have to worry about the details of their specific task. Obviously I don't know your system so I can't give detailed suggestions but this is how I did two decent-sized apps recently. They have about 30 servlets each. But the servlets are generally about 15 lines long. I ended up with a utility class that implemented the sorts of tasks needed by all the servlets. Poor man's delegation, perhaps.
Interface can't be instantiated. Instead, you should create a concrete class implementing the interface and instantiate this class.
I'm experimenting with a little web framework and stumbled across an issue with streams. There are handler methods like Response get(HttpServletRequest). From the frameworks perspective the response should offer an input stream for the response body. The framework reads this streams and writes the data to the underlying OutputStream of the Servlet API. But from the user's perspective an OutputStream is needed to write to.
Framework's perspective:
public interface Response {
InputStream getInputStream();
}
User's perspective:
public interface Response {
InputStream getOutputStream();
}
It should be used like this:
public void get(HttpServletRequest request) {
Response response = new Response(OK);
response.getOutputStream().write(...);
return response;
}
The problem is that I cannot create an outputstream without an output target (and don't want to write to a ByteArray buffer).
Any idea how to give the user an OutputStream without passing one in like in the Servlet API? I'd like to avoid output parameters.
Abstract/decorate the Request as well and get the Response from it instead.
E.g. in your front controller servlet:
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
Request request = new RequestImpl(req, res);
Action action = ActionFactory.getAction(req); // Do whatever way you do to locate the `Action`.
Response = action.get(request);
// ...
}
wherein RequestImpl look like this:
public class RequestImpl implements Request {
private HttpServletRequest request;
private HttpServletResponse response;
public RequestImpl(HttpServletRequest request, HttpServletResponse response) {
this.request = request;
this.response = response;
}
public Response newResponse(Status status) {
return new ResponseImpl(response, status);
// Add a boolean responseCreated to avoid creation of multiple responses? Illegal state!
}
public String getParameter(String name) { // Just another example of decorated method.
return request.getParameter(name);
}
// ...
}
and the ResponseImpl look like this:
public class ResponseImpl implements Response {
private HttpServletResponse response;
public ResponseImpl(HttpServletResponse response, Status status) {
this.response = response;
this.response.setStatus(status.getCode());
}
public OutputStream getOutputStream() {
return response.getOutputStream();
}
// ...
}
which you finally use like this in your Action:
public ActionImpl implements Action {
public Response get(Request request) {
Response response = request.newResponse(OK);
response.getOutputStream().write("body");
return response;
}
}
Alternatively, you can also create a Context which takes both the HttpServletRequest and HttpServletResponse and pass that in instead of Request. That's also less or more what the average MVC framework does. E.g.
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
Context context = new ContextImpl(req, res);
Action action = ActionFactory.getAction(req); // Do whatever way you do to locate the `Action`.
action.execute(context);
context.render(); // Do here whatever you'd initially to do with the obtained Response.
}
with
public ActionImpl implements Action {
public void execute(Context context) {
context.getResponseOutputStream().write("body");
}
}
That said, instead of reinventing, I'd suggest to have a look to existing API's as well. Depending on what you'd like to do, JSF, JAX-RS or JAX-WS might be what you're actually after. Unless this is for pure hobby purposes ;)
When you give the client an OutputStream, it HAS to be connected to something, either a buffer, socket, file or something else that can handle the data written to it.
One option might be to set it up as a PipedOutputStream connected to a PipedInputStream in another thread that handled the data. However, that would run into problems if the handling thread couldn't keep up with the client thread.
As Jim Garrison says, an OutputStream has to be connected to something... the bytes that are written to it have to go somewhere or else be discarded.
It seems to me like what you need to do is have Response wrap an InputStream directly. There could be a method on Response like:
void setContent(InputStream content);
Then, rather than writing to an OutputStream you provide, the user could provide whatever kind of InputStream they wanted and your framework would just copy that to the servlet OutputStream.
You could also allow them provide something implementing some interface similar to this:
interface OutputProducer {
void writeTo(OutputStream out) throws IOException;
}
In both cases you're basically allowing the user to provide a callback to use for writing to the OutputStream so that you don't need to pass it in.
I don't really know if any of that is worth it just to avoid using an output parameter, but those are options.