My log lines throw nullpointer exception when I run unit tests. I get no errors when I run it on local server or upload to appengine. Have I forgotten to include a test library somewhere?
java.lang.NullPointerException
at javax.servlet.GenericServlet.getServletContext(GenericServlet.java:160)
at javax.servlet.GenericServlet.log(GenericServlet.java:254)
at se.stuff.servlet.MyServlet.doGet(MyServlet.java:14)
at se.stuff.MyServletTest.test(MyServletTest.java:14)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
My servlet:
public class MyServlet extends HttpServlet {
#Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// Do stuff...
log("log stuff");
}
}
My test:
public class MyServletTest {
#Test
public void test() throws IOException {
MyServlet s = new MyServlet();
s.doGet(null, null);
}
}
The nulls in the test call s.doGet(null, null) cause the NullPointerException. The servlet is probably fine, but the test does not make sense. I suggest scrapping that test and first adding some content into doGet, then use QUnit to test your servlet from the outside.
Related
I was trying integrate Apache camel with Kafka and wrote a sample program to read a file and write to Kafka Topic. But I am getting below error while doing so. I could be able to do it the reverse way read from Kafka topic and write to a file.
Stacktrace
org.apache.kafka.common.errors.SerializationException: Can't convert value of class org.apache.camel.component.file.GenericFile to class org.apache.kafka.common.serialization.StringSerializer specified in value.serializer
[#0 - file://C:%5Cshare%5Cinput] KafkaProducer WARN No message key or partition key set
[#0 - file://C:%5Cshare%5Cinput] GenericFileOnCompletion WARN Rollback file strategy: org.apache.camel.component.file.strategy.GenericFileRenameProcessStrategy#7127845b for file: GenericFile[C:\share\input\file.txt]
[#0 - file://C:%5Cshare%5Cinput] DefaultErrorHandler ERROR Failed delivery for (MessageId: ID-L8-CWBL462-49953-1480494317350-0-21 on ExchangeId: ID-L8-CWBL462-49953-1480494317350-0-22). Exhausted after delivery attempt: 1 caught: org.apache.kafka.common.errors.SerializationException: Can't convert value of class org.apache.camel.component.file.GenericFile to class org.apache.kafka.common.serialization.StringSerializer specified in value.serializer
Code
#ContextName("myCdiCamelContext")
public class MyRoutes extends RouteBuilder {
#Inject
#Uri("file:C:\\share\\input?fileName=file.txt&noop=true")
private Endpoint inputEndpoint;
#Inject
#Uri("kafka:localhost:9092?topic=test&groupId=testing&autoOffsetReset=earliest&consumersCount=1")
private Endpoint resultEndpoint;
#Override
public void configure() throws Exception {
from(inputEndpoint)
.to(resultEndpoint);
}
}
After adding a new processor it worked for me
public void configure() throws Exception {
from(inputEndpoint).process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
exchange.getIn().setBody(exchange.getIn().getBody(),String.class);
exchange.getIn().setHeader(KafkaConstants.PARTITION_KEY, 0);
exchange.getIn().setHeader(KafkaConstants.KEY, "1");
}
})
.to(resultEndpoint);
}
How can we stop looping on camel splitter on specific exception?
The "stopOnException()" is stopping the looping for every exception, but instead I want to stop looping only on some specific exceptions. And if the exception is "HttpOperationFailedException", I want to stop looping based on response code.
For example if response code is "500" stop execution and if response code is 404 continue execution.
Is it possible?
Original Question
from("timer:categoryRouter?delay=0")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
exchange.getIn().setBody("A,F,B,D,C");
}
})
// tell Splitter to use the aggregation strategy which handles and ignores exceptions
.split(body(), new MyIgnoreFailureAggregationStrategy())
.stopOnException()
// log each splitted message
.log("Split line ${body}")
// and have them translated into a quote
.bean(WordTranslateBean.class)
// and send it to a mock
.to("mock:split")
.end()
// log the outgoing aggregated message
.log("Aggregated ${body}")
// and send it to a mock as well
.to("mock:result");
Bean which throws exception:
public class WordTranslateBean {
private Map<String, String> words = new HashMap<String, String>();
public WordTranslateBean() {
words.put("A", "Camel rocks");
words.put("B", "Hi mom");
words.put("C", "Yes it works");
}
public String translate(String key) throws HttpOperationFailedException {
if (!words.containsKey(key)) {
HttpOperationFailedException httpOperationFailedException = null;
if(key.equals("F")) {
httpOperationFailedException = new HttpOperationFailedException("uri",500,"Internal Server Error","location",null,"Key not a known word " + key);
}
else {
httpOperationFailedException = new HttpOperationFailedException("uri",404,"Resource Not Found","location",null,"Operation not supported on word " + key);
}
throw httpOperationFailedException;
}
return words.get(key);
}
}
Working Solution:
from("timer:categoryRouter?delay=0")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
exchange.getIn().setBody("A,F,B,D,C");
}
})
// tell Splitter to use the aggregation strategy which handles and ignores exceptions
.split(body(), new MyIgnoreFailureAggregationStrategy())
.stopOnException()
// log each splitted message
.log("Split line ${body}")
// and have them translated into a quote
.doTry()
.bean(WordTranslateBean.class)
// and send it to a mock
.to("mock:split")
.doCatch(HttpOperationFailedException.class)
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
HttpOperationFailedException e = (HttpOperationFailedException) exchange.getProperty(Exchange.EXCEPTION_CAUGHT);
if(e.getStatusCode()!=404){
throw e;
}
}
})
.end()
.end()
// log the outgoing aggregated message
.log("Aggregated ${body}")
// and send it to a mock as well
.to("mock:result");
Why don't you throw a custom exception based on a response code ? That's one option . Basically you can catch the original http exception , check the response code , throw your custom exception. Can you post your route ? It's easy to implement this way, just want to see how you have organised your routes .
Basically we still need to use "stopOnException" to stop the splitter when exception occurred. But to control on which exception the splitter should break, you can use "doTry..doCatch" block and in the respective catch block throw back the exception again.
from("timer:categoryRouter?delay=0")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
exchange.getIn().setBody("A,F,B,D,C");
}
})
// tell Splitter to use the aggregation strategy which handles and ignores exceptions
.split(body(), new MyIgnoreFailureAggregationStrategy())
// log each splitted message
.log("Split line ${body}")
// and have them translated into a quote
.doTry()
.bean(WordTranslateBean.class)
// and send it to a mock
.to("mock:split")
.doCatch(HttpOperationFailedException.class)
.log("Ignore Exception")
.doCatch(IOException.class)
.throwException(new IOException())
.doCatch(UnsupportedOperationException.class)
.log("Ignore Exception")
.end()
.end()
// log the outgoing aggregated message
.log("Aggregated ${body}")
// and send it to a mock as well
.to("mock:result");
If the exception is related to http and want to inspect the response code to act accordingly then you can my question which has the working solution.
You can catch the exceptions and decide what to do with them. Inside of your splitter:
<doTry>
<!-- Your Splitter logic here -->
<doCatch>
<exception>java.lang.IllegalStateException</exception>
<log message="This exception happened here, but not a problem.."/>
</doCatch>
<doCatch>
<exception>java.io.IOException</exception>
<log message="Big problem here. STOPPING.."/>
<stop/>
</doCatch>
<doFinally>
<to uri="mock:finally"/>
</doFinally>
</doTry>
I have a route like following
from(direct:start)
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
exchange.setProperty("doc_url", "http://myhost:5984/test/record/doc.csv");
}
}).setHeader(Exchange.HTTP_METHOD, constant("GET"))
.convertBodyTo(String.class)
.recipientList(header("doc_url")
.split().streaming.process(new MyProcessor());
I don't want to run apache couchdb every time for testing. I want to make this http endpoint refer to resource file in the codebase. How to write this?
you can use the Camel AdviceWith feature to intercept/replace endpoints for testing...
camelContext.getRouteDefinition("myRouteId")
.adviceWith(camelContext, new AdviceWithRouteBuilder() {
#Override
public void configure() throws Exception
{
interceptSendToEndpoint("couchdb:http://localhost/database)
.skipSendToOriginalEndpoint()
.to("http://localhost:5984/test/record/doc.csv");
}
});
I have developed a web service using cxf. In case of an error due to a request that doesn't respect the xsd schema asociated I would custom the error sent to the client. For that:
1- I have added a specific EventHandlerValidator and a specific FaultOutInterceptor in web-services.xml
<jaxws:endpoint id="getNewCustomerOrderId" implementor="#getNewCustomerOrderIdWS" address="/GetNewCustomerOrderId">
<jaxws:properties>
<entry key="jaxb-validation-event-handler">
<ref bean="getNewCustomerOrderIdEventHandlerValidator"/>
</entry>
<entry key="schema-validation-enabled" value="IN"/>
<entry key="set-jaxb-validation-event-handler" value="true"/>
</jaxws:properties>
<jaxws:outFaultInterceptors>
<ref bean="getNewCustomerOrderIdCXFFaultOutInterceptor"/>
</jaxws:outFaultInterceptors>
</jaxws:endpoint>`enter code here
2 - I have implemented these classes:
In the handleValidator I just throw my own exception with a code and message
public class GetNewCustomerOrderIdEventHandlerValidator implements ValidationEventHandler {
#Override
public boolean handleEvent(ValidationEvent event) {
throw new MyException(MyExceptionCode.ERCC_GNCOI_100, event.getMessage());
}
}
FaultExceptionInterceptor runs for every exception thrown during webservice call. I only want to catch MyException with code ERCC_GNCOI_100 for customizing it, so:
public class GetNewCustomerOrderIdCXFFaultOutInterceptor extends AbstractSoapInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(CreateCustomerOrderCXFFaultOutInterceptor.class);
#Inject
private CreateCustomerOrderFaultExceptionService createCustomerOrderFaultExceptionService;
private static final JAXBContext jaxbContext;
static {
try {
jaxbContext = JAXBContext.newInstance(CreateCustomerOrderException.class);
} catch (JAXBException e) {
LOGGER.error(CormoranMarker.TECH, "Error during JAXBContext instantiation");
throw new RuntimeException(e);
}
}
public GetNewCustomerOrderIdCXFFaultOutInterceptor() {
super(Phase.MARSHAL);
}
#Override
public void handleMessage(SoapMessage message) throws Fault {
Fault exceptionFault = (Fault) message.getContent(Exception.class);
exceptionFault.setMessage("My custom message");
if (exceptionFault.getCause() instanceof MyException) {
MyException myException = (MyException) exceptionFault
.getCause();
if (myException.getCode().equals(myException.ERCC_GNCOI_100)) {// validation
// schema
// errors
Element elt = buildExceptionFaultDetail(cormoranFunctionalException);
exceptionFault.setDetail(elt);
}
}
}
private Element buildExceptionFaultDetail(CormoranFunctionalException cormoranFunctionalException) {
// Build custom response
}
}
However, in the interceptor I'm not able to catch my exception:
Fault exceptionFault = (Fault) message.getContent(Exception.class);
This line gets an unmarshalling exception:
Unmarshalling Error: cvc-complex-type.2.4.a: Invalid content was found starting with element 'customerOrderType1'. One of '{customerOrderID, version, customerOrderType, depositDate}' is expected.
In the logs I see that My exception has been thrown:
12:32:27.338 [qtp200426125-38] ERROR c.o.c.c.e.MyException - [] - MyException : Non-respect du schéma (XSD) du WebService exposé par Cormoran : cvc-complex-type.2.4.a: Invalid content was found starting with element 'customerOrderType1'. One of '{customerOrderID, version, customerOrderType, depositDate}' is expected.
Could you help me?
Thank you in advance!
Auri
There are two problems with the Interceptor as written.
First, you need to set the new content to the message after you make your changes. To do that, you can add the following to the handleMessage method after your code
message.setContent(Exception.class, exceptionFault);
Second, the phase you chose was too late to make changes to the Fault object. It looks like PRE_STREAM is the latest phase that allows the change. The CXF Interceptor documentation has the full list of phases.
You can modify the message as below.
Fault exceptionFault = (Fault) message..getExchange().getContent(Exception.class);
One of my GAE classes is creating a [datastore Entity][1] from an HTML file:
Key parent = KeyFactory.createKey("movies", "movies");
Entity movie = new Entity("movie",System.currentTimeMillis(), parent);
setIfNotEmpty(movie, "director", Jsoup.parse(Html).select("td#f3").text());
setIfNotEmpty(movie, "year", Jsoup.parse(Html).select("td#f17").text());
....
When I'm trying to call this method in a JUnit test, the following exception is thrown:
java.lang.NullPointerException: No API environment is registered for this thread.
at com.google.appengine.api.datastore.DatastoreApiHelper.getCurrentAppId(DatastoreApiHelper.java:80)
at com.google.appengine.api.datastore.DatastoreApiHelper.getCurrentAppIdNamespace(DatastoreApiHelper.java:90)
at com.google.appengine.api.datastore.Key.<init>(Key.java:97)
at com.google.appengine.api.datastore.Key.<init>(Key.java:87)
at com.google.appengine.api.datastore.KeyFactory.createKey(KeyFactory.java:85)
at com.google.appengine.api.datastore.KeyFactory.createKey(KeyFactory.java:78)
at com.google.appengine.api.datastore.KeyFactory.createKey(KeyFactory.java:66)
at cinemasderot.Movie.parseMovieHtml(Movie.java:21)
at tests.TestParsing.testAddition(TestParsing.java:24)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
.....
The problem seems to be the creation of the Key in the first line of my code sample.
How can I create an Entity with a parent key from a Junit test?
Please read: https://developers.google.com/appengine/docs/java/tools/localunittesting
In short, you need something like this:
private final LocalServiceTestHelper helper =
new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());
#Before
public void setUp() {
helper.setUp();
}
#After
public void tearDown() {
helper.tearDown();
}