How to use SoapRequestMessageCallback method of com.consol.citrus.ws.message.callback.SoapRequestMessageCallback class

Best Citrus code snippet using com.consol.citrus.ws.message.callback.SoapRequestMessageCallback.SoapRequestMessageCallback

Source:SoapRequestMessageCallbackTest.java Github

copy

Full Screen

...37import static org.mockito.Mockito.*;38/**39 * @author Christoph Deppisch40 */41public class SoapRequestMessageCallbackTest extends AbstractTestNGUnitTest {42 private SoapMessage soapRequest = Mockito.mock(SoapMessage.class);43 private SoapBody soapBody = Mockito.mock(SoapBody.class);44 private SoapHeader soapHeader = Mockito.mock(SoapHeader.class);45 46 private String requestPayload = "<testMessage>Hello</testMessage>";47 48 @Test49 public void testSoapBody() throws TransformerException, IOException {50 Message testMessage = new DefaultMessage(requestPayload);51 SoapRequestMessageCallback callback = new SoapRequestMessageCallback(testMessage, new WebServiceEndpointConfiguration(), context);52 53 StringResult soapBodyResult = new StringResult();54 55 reset(soapRequest, soapBody);56 57 when(soapRequest.getSoapBody()).thenReturn(soapBody);58 when(soapBody.getPayloadResult()).thenReturn(soapBodyResult);59 60 callback.doWithMessage(soapRequest);61 62 Assert.assertEquals(soapBodyResult.toString(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + requestPayload);63 }64 65 @Test66 public void testSoapAction() throws TransformerException, IOException {67 Message testMessage = new DefaultMessage(requestPayload)68 .setHeader(SoapMessageHeaders.SOAP_ACTION, "soapAction");69 SoapRequestMessageCallback callback = new SoapRequestMessageCallback(testMessage, new WebServiceEndpointConfiguration(), context);70 71 reset(soapRequest, soapBody);72 73 when(soapRequest.getSoapBody()).thenReturn(soapBody);74 when(soapBody.getPayloadResult()).thenReturn(new StringResult());75 callback.doWithMessage(soapRequest);76 verify(soapRequest).setSoapAction("soapAction");77 }78 79 @Test80 public void testSoapHeaderContent() throws TransformerException, IOException {81 String soapHeaderContent = "<header>" + 82 "<operation>unitTest</operation>" + 83 "<messageId>123456789</messageId>" + 84 "</header>";85 86 Message testMessage = new DefaultMessage(requestPayload)87 .addHeaderData(soapHeaderContent);88 SoapRequestMessageCallback callback = new SoapRequestMessageCallback(testMessage, new WebServiceEndpointConfiguration(), context);89 90 StringResult soapHeaderResult = new StringResult();91 92 reset(soapRequest, soapBody, soapHeader);93 94 when(soapRequest.getSoapBody()).thenReturn(soapBody);95 when(soapBody.getPayloadResult()).thenReturn(new StringResult());96 97 when(soapRequest.getSoapHeader()).thenReturn(soapHeader);98 when(soapHeader.getResult()).thenReturn(soapHeaderResult);99 100 callback.doWithMessage(soapRequest);101 102 Assert.assertEquals(soapHeaderResult.toString(), soapHeaderContent);103 }104 @Test105 public void testMultipleSoapHeaderContent() throws TransformerException, IOException {106 String soapHeaderContent = "<header>" +107 "<operation>unitTest</operation>" +108 "<messageId>123456789</messageId>" +109 "</header>";110 Message testMessage = new DefaultMessage(requestPayload)111 .addHeaderData(soapHeaderContent)112 .addHeaderData("<AppInfo><appId>123456789</appId></AppInfo>");113 SoapRequestMessageCallback callback = new SoapRequestMessageCallback(testMessage, new WebServiceEndpointConfiguration(), context);114 StringResult soapHeaderResult = new StringResult();115 reset(soapRequest, soapBody, soapHeader);116 when(soapRequest.getSoapBody()).thenReturn(soapBody);117 when(soapBody.getPayloadResult()).thenReturn(new StringResult());118 when(soapRequest.getSoapHeader()).thenReturn(soapHeader);119 when(soapHeader.getResult()).thenReturn(soapHeaderResult);120 callback.doWithMessage(soapRequest);121 Assert.assertEquals(soapHeaderResult.toString(), soapHeaderContent + "<AppInfo><appId>123456789</appId></AppInfo>");122 }123 124 @Test125 public void testSoapHeader() throws TransformerException, IOException {126 Message testMessage = new DefaultMessage(requestPayload)127 .setHeader("operation", "unitTest")128 .setHeader("messageId", "123456789");129 SoapRequestMessageCallback callback = new SoapRequestMessageCallback(testMessage, new WebServiceEndpointConfiguration(), context);130 131 SoapHeaderElement soapHeaderElement = Mockito.mock(SoapHeaderElement.class);132 133 reset(soapRequest, soapBody, soapHeader, soapHeaderElement);134 135 when(soapRequest.getSoapBody()).thenReturn(soapBody);136 when(soapBody.getPayloadResult()).thenReturn(new StringResult());137 138 when(soapRequest.getSoapHeader()).thenReturn(soapHeader);139 when(soapHeader.addHeaderElement(eq(new QName("", "operation", "")))).thenReturn(soapHeaderElement);140 when(soapHeader.addHeaderElement(eq(new QName("", "messageId", "")))).thenReturn(soapHeaderElement);141 callback.doWithMessage(soapRequest);142 verify(soapHeaderElement).setText("unitTest");143 verify(soapHeaderElement).setText("123456789");144 }145 146 @Test147 public void testSoapHeaderQNameString() throws TransformerException, IOException {148 Message testMessage = new DefaultMessage(requestPayload)149 .setHeader("{http://www.citrus.com}citrus:operation", "unitTest")150 .setHeader("{http://www.citrus.com}citrus:messageId", "123456789");151 SoapRequestMessageCallback callback = new SoapRequestMessageCallback(testMessage, new WebServiceEndpointConfiguration(), context);152 153 SoapHeaderElement soapHeaderElement = Mockito.mock(SoapHeaderElement.class);154 155 reset(soapRequest, soapBody, soapHeader, soapHeaderElement);156 157 when(soapRequest.getSoapBody()).thenReturn(soapBody);158 when(soapBody.getPayloadResult()).thenReturn(new StringResult());159 160 when(soapRequest.getSoapHeader()).thenReturn(soapHeader);161 when(soapHeader.addHeaderElement(eq(new QName("http://www.citrus.com", "operation", "citrus")))).thenReturn(soapHeaderElement);162 when(soapHeader.addHeaderElement(eq(new QName("http://www.citrus.com", "messageId", "citrus")))).thenReturn(soapHeaderElement);163 callback.doWithMessage(soapRequest);164 verify(soapHeaderElement).setText("unitTest");165 verify(soapHeaderElement).setText("123456789");166 }167 168 @Test169 @SuppressWarnings("rawtypes")170 public void testSoapMimeHeader() throws TransformerException, IOException {171 Message testMessage = new DefaultMessage(requestPayload)172 .setHeader(SoapMessageHeaders.HTTP_PREFIX + "operation", "unitTest")173 .setHeader(SoapMessageHeaders.HTTP_PREFIX + "messageId", "123456789");174 SoapRequestMessageCallback callback = new SoapRequestMessageCallback(testMessage, new WebServiceEndpointConfiguration(), context);175 176 177 SaajSoapMessage saajSoapRequest = Mockito.mock(SaajSoapMessage.class);178 SoapEnvelope soapEnvelope = Mockito.mock(SoapEnvelope.class);179 SOAPMessage saajMessage = Mockito.mock(SOAPMessage.class);180 181 MimeHeaders mimeHeaders = new MimeHeaders();182 183 reset(saajSoapRequest, soapBody, soapHeader, soapEnvelope, saajMessage);184 185 when(saajSoapRequest.getEnvelope()).thenReturn(soapEnvelope);186 187 when(soapEnvelope.getBody()).thenReturn(soapBody);188 when(soapBody.getPayloadResult()).thenReturn(new StringResult());189 190 when(saajSoapRequest.getSaajMessage()).thenReturn(saajMessage);191 192 when(saajMessage.getMimeHeaders()).thenReturn(mimeHeaders);193 194 callback.doWithMessage(saajSoapRequest);195 Iterator it = mimeHeaders.getAllHeaders();196 Assert.assertEquals(((MimeHeader)it.next()).getName(), "operation");197 Assert.assertEquals(((MimeHeader)it.next()).getValue(), "123456789");198 Assert.assertFalse(it.hasNext());199 }200 201 @Test202 public void testSoapAttachment() throws TransformerException, IOException {203 SoapAttachment attachment = new SoapAttachment();204 attachment.setContentId("attContentId");205 attachment.setContent("This is a SOAP attachment\nwith multi-line");206 attachment.setContentType("plain/text");207 com.consol.citrus.ws.message.SoapMessage testMessage = new com.consol.citrus.ws.message.SoapMessage(requestPayload)208 .addAttachment(attachment);209 SoapRequestMessageCallback callback = new SoapRequestMessageCallback(testMessage, new WebServiceEndpointConfiguration(), context);210 211 reset(soapRequest, soapBody);212 213 when(soapRequest.getSoapBody()).thenReturn(soapBody);214 when(soapBody.getPayloadResult()).thenReturn(new StringResult());215 216 doAnswer(new Answer() {217 @Override218 public Object answer(InvocationOnMock invocation) throws Throwable {219 InputStreamSource contentStream = (InputStreamSource)invocation.getArguments()[1];220 BufferedReader reader = new BufferedReader(new InputStreamReader(contentStream.getInputStream()));221 Assert.assertEquals(reader.readLine(), "This is a SOAP attachment");222 Assert.assertEquals(reader.readLine(), "with multi-line");223 reader.close();...

Full Screen

Full Screen

Source:SoapRequestMessageCallback.java Github

copy

Full Screen

...26 * Web service message is filled with content from internal message representation.27 * 28 * @author Christoph Deppisch29 */30public class SoapRequestMessageCallback implements WebServiceMessageCallback {31 /** The internal message content source */32 private final Message message;33 /** Endpoint configuration */34 private final WebServiceEndpointConfiguration endpointConfiguration;35 /** Test context */36 private final TestContext context;37 38 /**39 * Constructor using internal message and endpoint configuration as fields.40 *41 * @param message42 * @param endpointConfiguration43 * @param context44 */45 public SoapRequestMessageCallback(Message message, WebServiceEndpointConfiguration endpointConfiguration, TestContext context) {46 this.message = message;47 this.endpointConfiguration = endpointConfiguration;48 this.context = context;49 }50 51 /**52 * Callback method called before request message is sent.53 */54 public void doWithMessage(WebServiceMessage requestMessage) throws IOException, TransformerException {55 endpointConfiguration.getMessageConverter().convertOutbound(requestMessage, message, endpointConfiguration, context);56 }57}...

Full Screen

Full Screen

SoapRequestMessageCallback

Using AI Code Generation

copy

Full Screen

1package com.consol.citrus;2import com.consol.citrus.annotations.CitrusTest;3import com.consol.citrus.dsl.testng.TestNGCitrusTestDesigner;4import com.consol.citrus.ws.message.callback.SoapRequestMessageCallback;5import org.springframework.http.HttpStatus;6import org.springframework.http.MediaType;7import org.springframework.oxm.Marshaller;8import org.springframework.oxm.XmlMappingException;9import org.springframework.ws.soap.SoapMessage;10import org.springframework.ws.soap.SoapVersion;11import org.springframework.ws.soap.saaj.SaajSoapMessage;12import org.springframework.xml.transform.StringResult;13import org.testng.annotations.Test;14import javax.xml.transform.TransformerException;15import java.io.IOException;16import java.util.HashMap;17import java.util.Map;18public class SoapRequestMessageCallbackTest extends TestNGCitrusTestDesigner {19 public void soapRequestMessageCallback() {20 description("Test to verify SoapRequestMessageCallback");21 http()22 .client("httpClient")23 .send()24 .post("/soap")25 .contentType(MediaType.APPLICATION_XML_VALUE)26 .header("Content-Type", "text/xml; charset=UTF-8")27 .header("Accept", "text/xml; charset=UTF-8")28 .header("Accept-Encoding", "gzip,deflate")29 .header("Connection", "Keep-Alive")30 .header("User-Agent", "Apache-HttpClient/4.5.2 (Java/1.8.0_121)")31 .messageCallback(new SoapRequestMessageCallback());32 http()33 .client("httpClient")34 .receive()35 .response(HttpStatus.OK)36 .contentType(MediaType.APPLICATION_XML_VALUE)37 .payload("<soapenv:Envelope xmlns

Full Screen

Full Screen

SoapRequestMessageCallback

Using AI Code Generation

copy

Full Screen

1package com.consol.citrus;2import com.consol.citrus.dsl.runner.TestRunner;3import com.consol.citrus.dsl.testng.TestNGCitrusTestDesigner;4import com.consol.citrus.ws.message.callback.SoapRequestMessageCallback;5public class SoapRequestMessageCallbackTest extends TestNGCitrusTestDesigner {6 public void configure() {7 TestRunner runner = this;8 SoapRequestMessageCallback soapRequestMessageCallback = new SoapRequestMessageCallback();9 soapRequestMessageCallback.setSoapAction("mySoapAction");10 soapRequestMessageCallback.setSoapVersion("1.1");11 soapRequestMessageCallback.setCharset("UTF-8");12 soapRequestMessageCallback.setContentType("text/xml");13 soapRequestMessageCallback.setSoapPrefix("soap");14 soapRequestMessageCallback.setSoapMessageName("soap:Envelope");15 soapRequestMessageCallback.setSoapMessagePrefix("soap");16 soapRequestMessageCallback.setSoapFaultName("soap:Fault");17 soapRequestMessageCallback.setSoapFaultPrefix("soap");18 soapRequestMessageCallback.setSoapFaultCodeName("soap:Code");19 soapRequestMessageCallback.setSoapFaultCodePrefix("soap");20 soapRequestMessageCallback.setSoapFaultSubCodeName("soap:Subcode");21 soapRequestMessageCallback.setSoapFaultSubCodePrefix("soap");22 soapRequestMessageCallback.setSoapFaultReasonName("soap:Reason");23 soapRequestMessageCallback.setSoapFaultReasonPrefix("soap");24 soapRequestMessageCallback.setSoapFaultNodeName("soap:Node");

Full Screen

Full Screen

SoapRequestMessageCallback

Using AI Code Generation

copy

Full Screen

1package com.consol.citrus.ws.actions;2import org.springframework.beans.factory.annotation.Autowired;3import org.springframework.beans.factory.annotation.Qualifier;4import org.springframework.context.annotation.Bean;5import org.springframework.context.annotation.Configuration;6import org.springframework.context.annotation.Import;7import org.springframework.core.io.ClassPathResource;8import org.springframework.ws.soap.SoapMessage;9import org.springframework.ws.soap.SoapVersion;10import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;11import org.springframework.ws.soap.saaj.SaajSoapMessageFactoryImpl;12import org.springframework.ws.soap.saaj.SaajSoapMessageUtils;13import com.consol.citrus.dsl.builder.BuilderSupport;14import com.consol.citrus.dsl.builder.ReceiveMessageBuilder;15import com.consol.citrus.dsl.builder.SendMessageBuilder;16import com.consol.citrus.dsl.builder.SoapActionBuilder;17import com.consol.citrus.dsl.endpoint.CitrusEndpoints;18import com.consol.citrus.dsl.junit.JUnit4CitrusTestRunner;19import com.consol.citrus.dsl.runner.TestRunner;20import com.consol.citrus.dsl.runner.TestRunnerAfterSuiteSupport;21import com.consol.citrus.dsl.runner.TestRunnerBeforeSuiteSupport;22import com.consol.citrus.dsl.runner.TestRunnerBeforeTestSupport;23import com.consol.citrus.dsl.runner.TestRunnerRunnerSupport;24import com.consol.citrus.http.client.HttpClient;25import com.consol.citrus.message.MessageType;26import com.consol.citrus.ws.client.WebServiceClient;27import com.consol.citrus.ws.message.callback.SoapRequestMessageCallback;28public class SoapRequestMessageCallbackTest extends JUnit4CitrusTestRunner {29 @Qualifier("soapClient")30 private WebServiceClient soapClient;31 @Qualifier("httpServer")32 private HttpClient httpServer;33 public void configure() {34 variable("requestPayload", new ClassPathResource("request-payload.xml"));35 soap(action -> action.client(soapClient)36 .send()37 .payload(new ClassPathResource("request-payload.xml"), new SoapRequestMessageCallback() {38 public void doWithMessage(SoapMessage message) {39 SaajSoapMessageUtils.getSaajMessage(message).get

Full Screen

Full Screen

SoapRequestMessageCallback

Using AI Code Generation

copy

Full Screen

1public void testSoapRequestMessageCallback() {2 MockWebServiceServer mockServer = MockWebServiceServer.createServer(webServiceTemplate);3}4public void testSoapResponseMessageCallback() {5 MockWebServiceServer mockServer = MockWebServiceServer.createServer(webServiceTemplate);6}7public void testSoapResponseMessageCallback() {8 MockWebServiceServer mockServer = MockWebServiceServer.createServer(webServiceTemplate);

Full Screen

Full Screen

SoapRequestMessageCallback

Using AI Code Generation

copy

Full Screen

1package com.consol.citrus.samples;2import org.springframework.context.annotation.Bean;3import org.springframework.context.annotation.Configuration;4import org.springframework.context.annotation.Import;5import org.springframework.ws.soap.SoapMessage;6import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;7import org.springframework.ws.soap.saaj.SaajSoapMessageUtils;8import org.springframework.ws.soap.saaj.SaajSoapMessageUtils.SaajSoapMessageCallback;9import com.consol.citrus.dsl.design.TestDesigner;10import com.consol.citrus.dsl.design.TestDesignerBeforeSuiteSupport;11import com.consol.citrus.dsl.endpoint.CitrusEndpoints;12import com.consol.citrus.ws.client.WebServiceClient;13import com.consol.citrus.ws.message.callback.SoapRequestMessageCallback;14@Import({ com.consol.citrus.dsl.CitrusEndpoints.class })15public class SoapRequestMessageCallbackConfig extends TestDesignerBeforeSuiteSupport {16 public WebServiceClient soapRequestMessageCallbackClient() {17 return CitrusEndpoints.soap()18 .client()19 .messageFactory(messageFactory())20 .build();21 }22 public SaajSoapMessageFactory messageFactory() {23 return new SaajSoapMessageFactory();24 }25 public void configure(TestDesigner testDesigner) {26 testDesigner.send(soapRequestMessageCallbackClient())27 .message()28 .messageCallback(new SoapRequestMessageCallback() {29 public void doWithMessage(SoapMessage soapMessage) {30 }31 });32 }33}34package com.consol.citrus.samples;35import org.springframework.context.annotation.Bean;36import org.springframework.context.annotation.Configuration;37import org

Full Screen

Full Screen

SoapRequestMessageCallback

Using AI Code Generation

copy

Full Screen

1public class 3 extends AbstractTestNGCitrusTest {2 public void 3() {3 variable("messageId", "urn:uuid:3");4 variable("correlationId", "urn:uuid:3");5 variable("timestamp", "2016-06-01T00:00:00.000Z");6 variable("sourceSystem", "3");7 variable("targetSystem", "3");8 variable("data", "3");9 variable("objectType", "3");10 variable("objectId", "3");11 variable("objectVersion", "3");12 variable("objectVersionId", "3");13 variable("objectVersionTs", "3");14 variable("objectVersionStatus", "3");15 variable("objectVersionStatusTs", "3");16 variable("objectVersionStatusBy", "3");17 variable("objectVersionStatusReason", "3");18 variable("objectVersionStatusReasonTs", "3");19 variable("objectVersionStatusReasonBy", "3");20 variable("objectVersionStatusReasonType", "3");21 variable("objectVersionStatusReasonTypeDesc", "3");22 variable("objectVersionStatusReasonTypeDescTs", "3");23 variable("objectVersionStatusReasonTypeDescBy", "3");24 variable("objectVersionStatusReasonTypeDescType", "3");25 variable("objectVersionStatusReasonTypeDescTypeDesc", "3");26 variable("objectVersionStatusReasonTypeDescTypeDescTs", "3");27 variable("objectVersionStatusReasonTypeDescTypeDescBy", "3");28 variable("objectVersionStatusReasonTypeDescTypeDescType", "3");29 variable("objectVersionStatusReasonTypeDescTypeDescTypeDesc", "3");30 variable("objectVersionStatusReasonTypeDescTypeDescTypeDescTs", "3");31 variable("objectVersionStatusReasonTypeDescTypeDescTypeDescBy", "3");32 variable("objectVersionStatusReasonTypeDescTypeDescTypeDescType", "3");33 variable("objectVersionStatusReasonTypeDescTypeDescTypeDescTypeDesc", "3");34 variable("objectVersionStatusReasonTypeDescTypeDescTypeDescTypeDescTs", "3");35 variable("objectVersionStatusReasonTypeDescTypeDescTypeDescTypeDescBy", "3");36 variable("objectVersionStatusReasonTypeDescTypeDescTypeDescTypeDescType", "3");

Full Screen

Full Screen

SoapRequestMessageCallback

Using AI Code Generation

copy

Full Screen

1package com.consol.citrus.samples;2import org.springframework.context.annotation.Bean;3import org.springframework.context.annotation.Configuration;4import org.springframework.context.annotation.ImportResource;5import org.springframework.ws.soap.SoapMessage;6import com.consol.citrus.dsl.endpoint.CitrusEndpoints;7import com.consol.citrus.dsl.runner.TestRunner;8import com.consol.citrus.dsl.runner.TestRunnerSupport;9import com.consol.citrus.dsl.testng.TestNGCitrusTestRunner;10import com.consol.citrus.http.client.HttpClient;11import com.consol.citrus.http.message.HttpMessage;12import com.consol.citrus.message.MessageType;13import com.consol.citrus.ws.message.callback.SoapRequestMessageCallback;14@ImportResource("classpath:com/consol/citrus/samples/SoapRequestMessageCallbackTest-context.xml")15public class SoapRequestMessageCallbackTest extends TestNGCitrusTestRunner {16 public HttpClient soapClient() {17 .http()18 .client()19 .build();20 }21 protected void configure() {22 http(httpActionBuilder -> httpActionBuilder23 .client(soapClient())24 .send()25 .messageType(MessageType.XML)26 .messageCallback(new SoapRequestMessageCallback() {27 public void doWithMessage(TestRunner runner, SoapMessage message) {28 message.setSoapAction("sayHello");29 }30 }));31 http(httpActionBuilder -> httpActionBuilder32 .client(soapClient())33 .receive()34 .messageType(MessageType.XML)35 }36 public static void main(String[] args) {37 TestRunnerSupport.runTest(SoapRequestMessageCallbackTest.class);38 }39}

Full Screen

Full Screen

SoapRequestMessageCallback

Using AI Code Generation

copy

Full Screen

1public class SoapRequestMessageCallback extends AbstractTestAction {2 public void doExecute(TestContext context) {3 SoapRequestMessageCallback soapRequestMessageCallback = new SoapRequestMessageCallback();4 }5}6public class SoapResponseMessageCallback extends AbstractTestAction {7 public void doExecute(TestContext context) {8 SoapResponseMessageCallback soapResponseMessageCallback = new SoapResponseMessageCallback();9 }10}11public class SoapResponseMessageCallback extends AbstractTestAction {12 public void doExecute(TestContext context) {13 SoapResponseMessageCallback soapResponseMessageCallback = new SoapResponseMessageCallback();14 }15}16public class WebServiceClient extends AbstractTestAction {17 public void doExecute(TestContext context) {18 WebServiceClient webServiceClient = new WebServiceClient();19 }20}21public class WebServiceClient extends AbstractTestAction {22 public void doExecute(TestContext context) {

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Citrus automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Most used method in SoapRequestMessageCallback

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful