public class UserRegistrationCustomEventHandler extends AbstractEventHandler {
JSONObject jsonObject = null;
private static final Log log = LogFactory.getLog(UserRegistrationCustomEventHandler.class);
#Override
public String getName() {
return "customClaimUpdate";
}
if (IdentityEventConstants.Event.POST_SET_USER_CLAIMS.equals(event.getEventName())) {
String tenantDomain = (String) event.getEventProperties()
.get(IdentityEventConstants.EventProperty.TENANT_DOMAIN);
String userName = (String) event.getEventProperties().get(IdentityEventConstants.EventProperty.USER_NAME);
Map<String, Object> eventProperties = event.getEventProperties();
String eventName = event.getEventName();
UserStoreManager userStoreManager = (UserStoreManager) eventProperties.get(IdentityEventConstants.EventProperty.USER_STORE_MANAGER);
// String userStoreDomain = UserCoreUtil.getDomainName(userStoreManager.getRealmConfiguration());
#SuppressWarnings("unchecked")
Map<String, String> claimValues = (Map<String, String>) eventProperties.get(IdentityEventConstants.EventProperty
.USER_CLAIMS);
String emailId = claimValues.get("http://wso2.org/claims/emailaddress");
userName = "USERS/"+userName;
JSONObject json = new JSONObject();
json.put("userName",userName );
json.put("emailId",emailId );
log.info("JSON:::::::"+json);
// Sample API
//String apiValue = "http://192.168.1.X:8080/SomeService/user/updateUserEmail?email=sujith#gmail.com&userName=USERS/sujith";
try {
URL url = new URL(cityAppUrl) ;
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setConnectTimeout(5000);
con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
con.setDoOutput(true);
con.setDoInput(true);
con.setRequestMethod("POST");
log.info("CONN:::::::::::::"+con);
OutputStream os = con.getOutputStream();
os.write(cityAppUrl.toString().getBytes("UTF-8"));
os.close();
InputStream in = new BufferedInputStream(con.getInputStream());
String result = org.apache.commons.io.IOUtils.toString(in, "UTF-8");
jsonObject = new JSONObject(result);
log.info("JSON OBJECT:::::::::"+jsonObject);
}
catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void init(InitConfig configuration) throws IdentityRuntimeException {
super.init(configuration);
}
#Override
public int getPriority(MessageContext messageContext) {
return 250;
}
}
I'm using wso2 identity server 5.10.0 and have to push the updated claim value to an API so I'm using a custom handler and have subscribed to POST_SET_USER_CLAIMS, i have to read the API value from deployment.toml file in jave code of the custom handler. So can any one please help here to read the value from deployment file
I can fetch the updated claim value in logs but im not able to get the API value. So can anyone help me here to read the value from deployment file.
Since the API path is required inside your custom event handler, let's define the API path value as one of the properties of the event handler.
Add the deployment.toml config as follows.
[[event_handler]]
name= "UserRegistrationCustomEventHandler"
subscriptions =["POST_SET_USER_CLAIMS"]
properties.apiPath = "http://192.168.1.X:8080/SomeService/user/updateUserEmail"
Once you restart the server identity-event.properties file populates the given configs.
In your custom event handler java code needs to read the config from identity-event.properties file. The file reading is done at the server startup and every config is loaded to the memory.
By adding this to your java code, you can load to configured value in the property.
configs.getModuleProperties().getProperty("UserRegistrationCustomEventHandler.apiPath")
NOTE: property name needs to be defined as <event_handler_name>.<property_name>
Here is a reference to such event hanlder's property loading code snippet https://github.com/wso2-extensions/identity-governance/blob/68e3f2d5e246b6a75f48e314ee1019230c662b55/components/org.wso2.carbon.identity.password.policy/src/main/java/org/wso2/carbon/identity/password/policy/handler/PasswordPolicyValidationHandler.java#L128-L133
I am developing a Java client which will create an application in WSO2 Identity Server through calling the OAuthAdminService. After some digging I found that registerOAuthApplicationData() method is the one used for creating an application in IS. Before calling the method, I have authenticated the admin user via login() method of AuthenticationAdminStub type. Even after such authentication the registerOAuthApplicationData() method make the IS console to print
[2016-04-26 13:08:52,577] WARN
{org.wso2.carbon.server.admin.module.handler.AuthenticationHandler} -
Illegal access attempt at [2016-04-26 13:08:52,0577] from IP address
127.0.0.1 while trying to authenticate access to service OAuthAdminService
and the application is not getting created in the IS database.
The code which I have tried goes as follows
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.apache.axis2.transport.http.HTTPConstants;
import org.wso2.carbon.authenticator.proxy.AuthenticationAdminStub;
import org.wso2.carbon.identity.oauth.OAuthAdminServicePortTypeProxy;
import org.wso2.carbon.identity.oauth.dto.xsd.OAuthConsumerAppDTO;
public class IdentityClientOne {
private final static String SERVER_URL = "https://localhost:9443/services/";
private final static String APP_ID = "myapp";
/**
* #param args
*/
public static void main(String[] args) {
AuthenticationAdminStub authstub = null;
ConfigurationContext configContext = null;
System.setProperty("javax.net.ssl.trustStore", "wso2carbon.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "wso2carbon");
try {
configContext = ConfigurationContextFactory.createConfigurationContextFromFileSystem(
"repo", "repo/conf/client.axis2.xml");
authstub = new AuthenticationAdminStub(configContext, SERVER_URL
+ "AuthenticationAdmin");
// Authenticates as a user having rights to add users.
if (authstub.login("admin", "admin", APP_ID)) {
System.out.println("admin authenticated");
OAuthConsumerAppDTO consumerApp = new OAuthConsumerAppDTO("Oauth-2.0",
"sample_app",
"",
"authorization_code implicit password client_credentials refresh_token urn:ietf:params:oauth:grant-type:saml2-bearer iwa:ntlm","","","");
OAuthAdminServicePortTypeProxy OAuthAdminProxy = new OAuthAdminServicePortTypeProxy();
OAuthAdminProxy.registerOAuthApplicationData(consumerApp);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Please help what should be done right ?
You have to access the stub via the authenticated session.
Could you try below.
public class Test {
private final static String SERVER_URL = "https://localhost:9443/services/";
public static void main(String[] args) throws RemoteException, OAuthAdminServiceException {
OAuthAdminServiceStub stub = new OAuthAdminServiceStub(null, SERVER_URL + "OAuthAdminService");
ServiceClient client = stub._getServiceClient();
authenticate(client);
OAuthConsumerAppDTO consumerAppDTO = new OAuthConsumerAppDTO();
consumerAppDTO.setApplicationName("sample-app");
consumerAppDTO.setCallbackUrl("http://localhost:8080/playground2/oauth2client");
consumerAppDTO.setOAuthVersion("OAuth-2.0");
consumerAppDTO.setGrantTypes("authorization_code implicit password client_credentials refresh_token "
+ "urn:ietf:params:oauth:grant-type:saml2-bearer iwa:ntlm");
stub.registerOAuthApplicationData(consumerAppDTO);
}
public static void authenticate(ServiceClient client) {
Options option = client.getOptions();
HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator();
auth.setUsername("admin");
auth.setPassword("admin");
auth.setPreemptiveAuthentication(true);
option.setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE, auth);
option.setManageSession(true);
}
}
Im doing restfull webservices with soap using websphere and RAD. After generating my javaclient classes when I run the test class I get the following error. Ive been searching the web but not finding the correct solution. PLEASE HELP!
ERROR:
Check method call
org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted.
at org.apache.xerces.dom.CoreDocumentImpl.insertBefore(Unknown Source)
at org.apache.xerces.dom.NodeImpl.appendChild(Unknown Source)
at com.ibm.ws.webservices.engine.xmlsoap.SOAPPart.appendChild(SOAPPart.java:282)
at com.sun.xml.internal.bind.marshaller.SAX2DOMEx.startElement(SAX2DOMEx.java:177)
at com.sun.xml.internal.ws.message.AbstractMessageImpl.writeTo(AbstractMessageImpl.java:159)
at com.sun.xml.internal.ws.message.AbstractMessageImpl.readAsSOAPMessage(AbstractMessageImpl.java:194)
at com.sun.xml.internal.ws.handler.SOAPMessageContextImpl.getMessage(SOAPMessageContextImpl.java:80)
at test.CustomSoapHandler.handleMessage(CustomSoapHandler.java:37)
at test.CustomSoapHandler.handleMessage(CustomSoapHandler.java:1)
at com.sun.xml.internal.ws.handler.HandlerProcessor.callHandleMessage(HandlerProcessor.java:293)
at com.sun.xml.internal.ws.handler.HandlerProcessor.callHandlersRequest(HandlerProcessor.java:134)
at com.sun.xml.internal.ws.handler.ClientSOAPHandlerTube.callHandlersOnRequest(ClientSOAPHandlerTube.java:139)
at com.sun.xml.internal.ws.handler.HandlerTube.processRequest(HandlerTube.java:117)
at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Fiber.java:599)
at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Fiber.java:558)
at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Fiber.java:543)
at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Fiber.java:440)
at com.sun.xml.internal.ws.client.Stub.process(Stub.java:223)
at com.sun.xml.internal.ws.client.sei.SEIStub.doProcess(SEIStub.java:136)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:110)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:90)
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:119)
at $Proxy33.getHistory(Unknown Source)
at test.ServiceTest.historyTest(ServiceTest.java:64)
at test.ServiceTest.main(ServiceTest.java:100)
Exception in thread "main" java.lang.ExceptionInInitializerError
at java.lang.J9VMInternals.initialize(J9VMInternals.java:227)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:119)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:90)
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:119)
at $Proxy33.getHistory(Unknown Source)
at test.ServiceTest.historyTest(ServiceTest.java:64)
at test.ServiceTest.main(ServiceTest.java:100)
Caused by: java.lang.ClassCastException: com.ibm.xml.xlxp2.jaxb.JAXBContextImpl incompatible with com.sun.xml.internal.bind.api.JAXBRIContext
at java.lang.ClassCastException.<init>(ClassCastException.java:58)
at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.<clinit>(SOAPFaultBuilder.java:545)
at java.lang.J9VMInternals.initializeImpl(Native Method)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:205)
... 6 more
Test Class:
package test;
import be.ipc.css.ws.GcssWebServiceService;
import be.ipc.css.ws.IGcssWebService;
import be.ipc.css.ws.InvalidItemIdStructureFault_Exception;
import be.ipc.css.ws.ProductNotAllowedFault_Exception;
import be.ipc.css.ws.common.Product;
import be.ipc.css.ws.history.GetHistoryInput;
import be.ipc.css.ws.history_output.GetHistoryOutput;
import be.ipc.css.ws.history_output.HistoryItem;
import be.ipc.css.ws.history_output.Type;
import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Service;
import javax.xml.ws.handler.Handler;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/**
* <strong>Project: TODO: project name</strong><br/>
* <b>Url:</b> TODO: url<br/>
* <b>Date:</b> 15.05.14<br/>
* <b>Time:</b> 23:42 <br/>
* Copyright(C) 2014 IT Service Plus <br/>
* <b>Description:</b><br/>
* TODO: description
*/
public class ServiceTest {
private static Service webService;
private static IGcssWebService servicePort;
public void initService() throws MalformedURLException {
URL url = new URL("http://cs-demo.ipc.be/CSS_UA2/services/gcssWebService/1.0");
QName qname = new QName("http://ws.css.ipc.be/", "GcssWebServiceService");
/*java.util.Properties props = System.getProperties();
props.setProperty("http.proxyHost", "proxy.test.com");
props.setProperty("http.proxyPort", "8080");*/
webService = GcssWebServiceService.create(url, qname);
servicePort = webService.getPort(IGcssWebService.class);
try {
CustomSoapHandler sh = new CustomSoapHandler("user_us", "*******");
List<Handler> new_handlerChain = new ArrayList<Handler>();
new_handlerChain.add(sh);
((BindingProvider)servicePort).getBinding().setHandlerChain(new_handlerChain);
} catch (Throwable e) {
e.printStackTrace();
}
//((BindingProvider)servicePort).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "user_us");
//((BindingProvider)servicePort).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "*******");
}
public void historyTest() throws ProductNotAllowedFault_Exception, InvalidItemIdStructureFault_Exception {
GetHistoryInput input = new GetHistoryInput();
input.setItemId("CC027607063NL");
input.setProduct(Product.EPG);
System.out.println("Check method call");
GetHistoryOutput output = servicePort.getHistory(input);
System.out.println("Check result");
//Assert.assertNotNull(output);
//Assert.assertNotNull(output.getHistory());
//Assert.assertNotNull(output.getHistory().getHistoryItem());
System.out.println("Received: " + output.getHistory().getHistoryItem().size() + "elements:");
System.out.println("-----------------------");
for(int i=0;i<output.getHistory().getHistoryItem().size();i++) {
HistoryItem it = output.getHistory().getHistoryItem().get(i);
System.out.println("#" + i + ": id=" + it.getId() + ", type=" + it.getType().value());
}
System.out.println("Check 3 history items");
//Assert.assertEquals(3, output.getHistory().getHistoryItem().size());
HistoryItem it1 = output.getHistory().getHistoryItem().get(0);
HistoryItem it2 = output.getHistory().getHistoryItem().get(1);
HistoryItem it3 = output.getHistory().getHistoryItem().get(2);
/*Assert.assertEquals(Type.QUMQ, it1.getType());
Assert.assertEquals(161L, it1.getId());
Assert.assertEquals(Type.SUM, it2.getType());
Assert.assertEquals(652L, it2.getId());
Assert.assertEquals(Type.L_1_Q, it3.getType());
Assert.assertEquals(13742L, it3.getId());*/
}
public static void main(String[] args) {
ServiceTest test = new ServiceTest();
try {
test.initService();
test.historyTest();
} catch(Exception e ){
e.printStackTrace();
}
}
}
Soap Handler:
package test;
import javax.xml.namespace.QName;
import javax.xml.soap.*;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import java.util.Set;
/**
* <strong>Project: TODO: project name</strong><br/>
* <b>Url:</b> TODO: url<br/>
* <b>Date:</b> 16.05.14<br/>
* <b>Time:</b> 0:48 <br/>
* Copyright(C) 2014 IT Service Plus <br/>
* <b>Description:</b><br/>
* TODO: description
*/
public class CustomSoapHandler implements SOAPHandler<SOAPMessageContext> {
private static final String AUTH_PREFIX = "wsse";
private static final String AUTH_NS =
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
private String username;
private String password;
public CustomSoapHandler(String username, String password) {
this.username = username;
this.password = password;
}
public boolean handleMessage(SOAPMessageContext context) {
try {
SOAPEnvelope envelope =
context.getMessage().getSOAPPart().getEnvelope();
SOAPFactory soapFactory = SOAPFactory.newInstance();
SOAPElement wsSecHeaderElm =
soapFactory.createElement("Security", AUTH_PREFIX, AUTH_NS);
Name wsSecHdrMustUnderstandAttr =
soapFactory.createName("mustUnderstand", "S",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
wsSecHeaderElm.addAttribute(wsSecHdrMustUnderstandAttr, "1");
SOAPElement userNameTokenElm =
soapFactory.createElement("UsernameToken", AUTH_PREFIX,
AUTH_NS);
Name userNameTokenIdName =
soapFactory.createName("id", "wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
userNameTokenElm.addAttribute(userNameTokenIdName,
"UsernameToken-ORbTEPzNsEMDfzrI9sscVA22");
SOAPElement userNameElm =
soapFactory.createElement("Username", AUTH_PREFIX, AUTH_NS);
userNameElm.addTextNode(username);
SOAPElement passwdElm =
soapFactory.createElement("Password", AUTH_PREFIX, AUTH_NS);
Name passwdTypeAttr = soapFactory.createName("Type");
passwdElm.addAttribute(passwdTypeAttr,
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
passwdElm.addTextNode(password);
userNameTokenElm.addChildElement(userNameElm);
userNameTokenElm.addChildElement(passwdElm);
wsSecHeaderElm.addChildElement(userNameTokenElm);
if (envelope.getHeader() == null) {
SOAPHeader sh = envelope.addHeader();
sh.addChildElement(wsSecHeaderElm);
} else {
SOAPHeader sh = envelope.getHeader();
sh.addChildElement(wsSecHeaderElm);
}
} catch (Throwable e) {
e.printStackTrace();
}
return true;
}
#Override
public boolean handleFault(SOAPMessageContext context) {
return false; //To change body of implemented methods use File | Settings | File Templates.
}
#Override
public void close(MessageContext context) {
//To change body of implemented methods use File | Settings | File Templates.
}
#Override
public Set<QName> getHeaders() {
return null;
}
}
The main reason for your error is incompatible JAXB implementation classes:
aused by: java.lang.ClassCastException: com.ibm.xml.xlxp2.jaxb.JAXBContextImpl incompatible with com.sun.xml.internal.bind.api.JAXBRIContext
Probably the best way to fix this is packaging your own version of JAXB within your application(inside the lib folder) and than change the class loader from WebSphere to be Parent Last.
After that, restart and try it again. If still doesn't work you can try adding your JAXB implementation libraries directly to the Application Server classloader. You can do that creating a directory under $WEBSPHERE_HOME/AppServer/classes and placing your JAXB implementation classes there. Be aware that this approach adds the dropped jars to all WebSphere instances running using this binary codebase.
You can learn more about WebSphere classloaders.
Hope this helps.
Getting Error while consuming webservices in java through SOAP approach. Plz suggest, i am stuck in this for last 10 days. I am using this server for webservices "http://www.webservicex.net/globalweather.asmx"
Error:
Exception in thread "main" [SOAPException: faultCode=SOAP-ENV:Client; msg=Error
opening socket: Connection timed out: connect;
targetException=java.lang.IllegalArgumentException: Error opening
socket: Connection timed out: connect]
at org.apache.soap.transport.http.SOAPHTTPConnection.se(SOAPHTTPConnection.java:324)
at org.apache.soap.rpc.Call.invoke(Call.java:205)
at com.check.ClientNet.main(ClientNet.java:47)
My java code is :
package com.check;
import java.net.*;
import java.util.*;
import org.apache.soap.*;
import org.apache.soap.encoding.SOAPMappingRegistry;
import org.apache.soap.rpc.*;
import org.apache.soap.encoding.soapenc.StringDeserializer;
import org.apache.soap.util.xml.QName;
import com.check.ProxyAuthenticator;
public class ClientNet {
public static void main (String[] args)
throws Exception {
Properties properties = System.getProperties();
properties.put("http.proxyHost", "10.136.236.30");
properties.put("http.proxyPort", "8080");
properties.put("http.proxyUser", "bnkishore");
properties.put("http.proxyPassword","XXXX");
Properties newprops = new Properties(properties);
System.setProperties(newprops);
String username = System.getProperty("http.proxyUser");
String password = System.getProperty("http.proxyPassword");
if (username != null && !username.equals("")) {
Authenticator.setDefault(new ProxyAuthenticator(username, password));
}
System.out.println("\n\nCalling the SOAP Server:\n\n");
//http://www.webservicex.net/globalweather.asmx
URL url = new URL ("http://www.webservicex.net/globalweather.asmx");
String CountryName = "India";
Call call = new Call();
SOAPMappingRegistry soapMappingRegistry = new SOAPMappingRegistry();
soapMappingRegistry.mapTypes(Constants.NS_URI_SOAP_ENC, new QName("http://www.webserviceX.NET", "globalweather"),null,null, new StringDeserializer());
call.setTargetObjectURI("http://www.webserviceX.NET");
call.setMethodName("GetCitiesByCountry");
call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);
Vector<Parameter> params = new Vector<Parameter>();
params.addElement(new Parameter("CountryName", String.class, CountryName, null));
call.setParams (params);
System.out.print("The SOAP Server says: ");
Response resp = call.invoke(url, " ");
if (resp.generatedFault()) {
Fault fault = resp.getFault();
System.out.println("\nOuch, the call failed: ");
System.out.println(" Fault Code = " + fault.getFaultCode());
System.out.println(" Fault String = " + fault.getFaultString());
} else {
Parameter result = resp.getReturnValue();
System.out.print(result.getValue());
System.out.println();
}
}
}
And ProxyAuthencator code is :
package com.check;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
public class ProxyAuthenticator extends Authenticator {
private String userName, passWord;
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(userName,passWord.toCharArray());
}
public ProxyAuthenticator(String userName, String password) {
this.userName = userName;
this.passWord = password;
getPasswordAuthentication();
}
}
Thanks.
There is a timeout, that means you client is not reaching the server. Check connectivity. For dealing with a proxy, additionally to your ProxyAuthenticator you need to add few system properties: proxySet, proxyHost and proxyPort. If you are using maven, you can do it in this way:
mvn jetty:run -DproxySet=true -DproxyHost=proxy.indra.es -DproxyPort=8080
I have created a web system using Java Servlets and now want to make JUnit testing. My dataManager is just a basic piece of code that submits it to the database. How would you test a Servlet with JUnit?
My code example that allows a user to register/sign up, which is submitted from my main page via AJAX:
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
// Get parameters
String userName = request.getParameter("username");
String password = request.getParameter("password");
String name = request.getParameter("name");
try {
// Load the database driver
Class.forName("com.mysql.jdbc.Driver");
//pass reg details to datamanager
dataManager = new DataManager();
//store result as string
String result = dataManager.register(userName, password, name);
//set response to html + no cache
response.setContentType("text/html");
response.setHeader("Cache-Control", "no-cache");
//send response with register result
response.getWriter().write(result);
} catch(Exception e){
System.out.println("Exception is :" + e);
}
}
You can do this using Mockito to have the mock return the correct params, verify they were indeed called (optionally specify number of times), write the 'result' and verify it's correct.
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import java.io.*;
import javax.servlet.http.*;
import org.apache.commons.io.FileUtils;
import org.junit.Test;
public class TestMyServlet extends Mockito{
#Test
public void testServlet() throws Exception {
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
when(request.getParameter("username")).thenReturn("me");
when(request.getParameter("password")).thenReturn("secret");
StringWriter stringWriter = new StringWriter();
PrintWriter writer = new PrintWriter(stringWriter);
when(response.getWriter()).thenReturn(writer);
new MyServlet().doPost(request, response);
verify(request, atLeast(1)).getParameter("username"); // only if you want to verify username was called...
writer.flush(); // it may not have been flushed yet...
assertTrue(stringWriter.toString().contains("My expected string"));
}
}
First off, in a real application, you would never get database connection info in a servlet; you would configure it in your app server.
There are ways, however, of testing Servlets without having a container running. One is to use mock objects. Spring provides a set of very useful mocks for things like HttpServletRequest, HttpServletResponse, HttpServletSession, etc:
http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/mock/web/package-summary.html
Using these mocks, you could test things like
What happens if username is not in the request?
What happens if username is in the request?
etc
You could then do stuff like:
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.junit.Before;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
public class MyServletTest {
private MyServlet servlet;
private MockHttpServletRequest request;
private MockHttpServletResponse response;
#Before
public void setUp() {
servlet = new MyServlet();
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
}
#Test
public void correctUsernameInRequest() throws ServletException, IOException {
request.addParameter("username", "scott");
request.addParameter("password", "tiger");
servlet.doPost(request, response);
assertEquals("text/html", response.getContentType());
// ... etc
}
}
I find Selenium tests more useful with integration or functional (end-to-end) testing. I am working with trying to use org.springframework.mock.web, but I am not very far along. I am attaching a sample controller with a jMock test suite.
First, the Controller:
package com.company.admin.web;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
import com.company.admin.domain.PaymentDetail;
import com.company.admin.service.PaymentSearchService;
import com.company.admin.service.UserRequestAuditTrail;
import com.company.admin.web.form.SearchCriteria;
/**
* Controls the interactions regarding to the refunds.
*
* #author slgelma
*
*/
#Controller
#SessionAttributes({"user", "authorization"})
public class SearchTransactionController {
public static final String SEARCH_TRANSACTION_PAGE = "searchtransaction";
private PaymentSearchService searchService;
//private Validator searchCriteriaValidator;
private UserRequestAuditTrail notifications;
#Autowired
public void setSearchService(PaymentSearchService searchService) {
this.searchService = searchService;
}
#Autowired
public void setNotifications(UserRequestAuditTrail notifications) {
this.notifications = notifications;
}
#RequestMapping(value="/" + SEARCH_TRANSACTION_PAGE)
public String setUpTransactionSearch(Model model) {
SearchCriteria searchCriteria = new SearchCriteria();
model.addAttribute("searchCriteria", searchCriteria);
notifications.transferTo(SEARCH_TRANSACTION_PAGE);
return SEARCH_TRANSACTION_PAGE;
}
#RequestMapping(value="/" + SEARCH_TRANSACTION_PAGE, method=RequestMethod.POST, params="cancel")
public String cancelSearch() {
notifications.redirectTo(HomeController.HOME_PAGE);
return "redirect:/" + HomeController.HOME_PAGE;
}
#RequestMapping(value="/" + SEARCH_TRANSACTION_PAGE, method=RequestMethod.POST, params="execute")
public String executeSearch(
#ModelAttribute("searchCriteria") #Valid SearchCriteria searchCriteria,
BindingResult result, Model model,
SessionStatus status) {
//searchCriteriaValidator.validate(criteria, result);
if (result.hasErrors()) {
notifications.transferTo(SEARCH_TRANSACTION_PAGE);
return SEARCH_TRANSACTION_PAGE;
} else {
PaymentDetail payment =
searchService.getAuthorizationFor(searchCriteria.geteWiseTransactionId());
if (payment == null) {
ObjectError error = new ObjectError(
"eWiseTransactionId", "Transaction not found");
result.addError(error);
model.addAttribute("searchCriteria", searchCriteria);
notifications.transferTo(SEARCH_TRANSACTION_PAGE);
return SEARCH_TRANSACTION_PAGE;
} else {
model.addAttribute("authorization", payment);
notifications.redirectTo(PaymentDetailController.PAYMENT_DETAIL_PAGE);
return "redirect:/" + PaymentDetailController.PAYMENT_DETAIL_PAGE;
}
}
}
}
Next, the test:
package test.unit.com.company.admin.web;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.support.SessionStatus;
import com.company.admin.domain.PaymentDetail;
import com.company.admin.service.PaymentSearchService;
import com.company.admin.service.UserRequestAuditTrail;
import com.company.admin.web.HomeController;
import com.company.admin.web.PaymentDetailController;
import com.company.admin.web.SearchTransactionController;
import com.company.admin.web.form.SearchCriteria;
/**
* Tests the behavior of the SearchTransactionController.
* #author slgelma
*
*/
#RunWith(JMock.class)
public class SearchTransactionControllerTest {
private final Mockery context = new JUnit4Mockery();
private final SearchTransactionController controller = new SearchTransactionController();
private final PaymentSearchService searchService = context.mock(PaymentSearchService.class);
private final UserRequestAuditTrail notifications = context.mock(UserRequestAuditTrail.class);
private final Model model = context.mock(Model.class);
/**
* #throws java.lang.Exception
*/
#Before
public void setUp() throws Exception {
controller.setSearchService(searchService);
controller.setNotifications(notifications);
}
#Test
public void setUpTheSearchForm() {
final String target = SearchTransactionController.SEARCH_TRANSACTION_PAGE;
context.checking(new Expectations() {{
oneOf(model).addAttribute(
with(any(String.class)), with(any(Object.class)));
oneOf(notifications).transferTo(with(any(String.class)));
}});
String nextPage = controller.setUpTransactionSearch(model);
assertThat("Controller is not requesting the correct form",
target, equalTo(nextPage));
}
#Test
public void cancelSearchTest() {
final String target = HomeController.HOME_PAGE;
context.checking(new Expectations(){{
never(model).addAttribute(with(any(String.class)), with(any(Object.class)));
oneOf(notifications).redirectTo(with(any(String.class)));
}});
String nextPage = controller.cancelSearch();
assertThat("Controller is not requesting the correct form",
nextPage, containsString(target));
}
#Test
public void executeSearchWithNullTransaction() {
final String target = SearchTransactionController.SEARCH_TRANSACTION_PAGE;
final SearchCriteria searchCriteria = new SearchCriteria();
searchCriteria.seteWiseTransactionId(null);
final BindingResult result = context.mock(BindingResult.class);
final SessionStatus status = context.mock(SessionStatus.class);
context.checking(new Expectations() {{
allowing(result).hasErrors(); will(returnValue(true));
never(model).addAttribute(with(any(String.class)), with(any(Object.class)));
never(searchService).getAuthorizationFor(searchCriteria.geteWiseTransactionId());
oneOf(notifications).transferTo(with(any(String.class)));
}});
String nextPage = controller.executeSearch(searchCriteria, result, model, status);
assertThat("Controller is not requesting the correct form",
target, equalTo(nextPage));
}
#Test
public void executeSearchWithEmptyTransaction() {
final String target = SearchTransactionController.SEARCH_TRANSACTION_PAGE;
final SearchCriteria searchCriteria = new SearchCriteria();
searchCriteria.seteWiseTransactionId("");
final BindingResult result = context.mock(BindingResult.class);
final SessionStatus status = context.mock(SessionStatus.class);
context.checking(new Expectations() {{
allowing(result).hasErrors(); will(returnValue(true));
never(model).addAttribute(with(any(String.class)), with(any(Object.class)));
never(searchService).getAuthorizationFor(searchCriteria.geteWiseTransactionId());
oneOf(notifications).transferTo(with(any(String.class)));
}});
String nextPage = controller.executeSearch(searchCriteria, result, model, status);
assertThat("Controller is not requesting the correct form",
target, equalTo(nextPage));
}
#Test
public void executeSearchWithTransactionNotFound() {
final String target = SearchTransactionController.SEARCH_TRANSACTION_PAGE;
final String badTransactionId = "badboy";
final PaymentDetail transactionNotFound = null;
final SearchCriteria searchCriteria = new SearchCriteria();
searchCriteria.seteWiseTransactionId(badTransactionId);
final BindingResult result = context.mock(BindingResult.class);
final SessionStatus status = context.mock(SessionStatus.class);
context.checking(new Expectations() {{
allowing(result).hasErrors(); will(returnValue(false));
atLeast(1).of(model).addAttribute(with(any(String.class)), with(any(Object.class)));
oneOf(searchService).getAuthorizationFor(with(any(String.class)));
will(returnValue(transactionNotFound));
oneOf(result).addError(with(any(ObjectError.class)));
oneOf(notifications).transferTo(with(any(String.class)));
}});
String nextPage = controller.executeSearch(searchCriteria, result, model, status);
assertThat("Controller is not requesting the correct form",
target, equalTo(nextPage));
}
#Test
public void executeSearchWithTransactionFound() {
final String target = PaymentDetailController.PAYMENT_DETAIL_PAGE;
final String goodTransactionId = "100000010";
final PaymentDetail transactionFound = context.mock(PaymentDetail.class);
final SearchCriteria searchCriteria = new SearchCriteria();
searchCriteria.seteWiseTransactionId(goodTransactionId);
final BindingResult result = context.mock(BindingResult.class);
final SessionStatus status = context.mock(SessionStatus.class);
context.checking(new Expectations() {{
allowing(result).hasErrors(); will(returnValue(false));
atLeast(1).of(model).addAttribute(with(any(String.class)), with(any(Object.class)));
oneOf(searchService).getAuthorizationFor(with(any(String.class)));
will(returnValue(transactionFound));
oneOf(notifications).redirectTo(with(any(String.class)));
}});
String nextPage = controller.executeSearch(searchCriteria, result, model, status);
assertThat("Controller is not requesting the correct form",
nextPage, containsString(target));
}
}
I hope this might help.
Updated Feb 2018: OpenBrace Limited has closed down, and its ObMimic product is no longer supported.
Here's another alternative, using OpenBrace's ObMimic library of Servlet API test-doubles (disclosure: I'm its developer).
package com.openbrace.experiments.examplecode.stackoverflow5434419;
import static org.junit.Assert.*;
import com.openbrace.experiments.examplecode.stackoverflow5434419.YourServlet;
import com.openbrace.obmimic.mimic.servlet.ServletConfigMimic;
import com.openbrace.obmimic.mimic.servlet.http.HttpServletRequestMimic;
import com.openbrace.obmimic.mimic.servlet.http.HttpServletResponseMimic;
import com.openbrace.obmimic.substate.servlet.RequestParameters;
import org.junit.Before;
import org.junit.Test;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Example tests for {#link YourServlet#doPost(HttpServletRequest,
* HttpServletResponse)}.
*
* #author Mike Kaufman, OpenBrace Limited
*/
public class YourServletTest {
/** The servlet to be tested by this instance's test. */
private YourServlet servlet;
/** The "mimic" request to be used in this instance's test. */
private HttpServletRequestMimic request;
/** The "mimic" response to be used in this instance's test. */
private HttpServletResponseMimic response;
/**
* Create an initialized servlet and a request and response for this
* instance's test.
*
* #throws ServletException if the servlet's init method throws such an
* exception.
*/
#Before
public void setUp() throws ServletException {
/*
* Note that for the simple servlet and tests involved:
* - We don't need anything particular in the servlet's ServletConfig.
* - The ServletContext isn't relevant, so ObMimic can be left to use
* its default ServletContext for everything.
*/
servlet = new YourServlet();
servlet.init(new ServletConfigMimic());
request = new HttpServletRequestMimic();
response = new HttpServletResponseMimic();
}
/**
* Test the doPost method with example argument values.
*
* #throws ServletException if the servlet throws such an exception.
* #throws IOException if the servlet throws such an exception.
*/
#Test
public void testYourServletDoPostWithExampleArguments()
throws ServletException, IOException {
// Configure the request. In this case, all we need are the three
// request parameters.
RequestParameters parameters
= request.getMimicState().getRequestParameters();
parameters.set("username", "mike");
parameters.set("password", "xyz#zyx");
parameters.set("name", "Mike");
// Run the "doPost".
servlet.doPost(request, response);
// Check the response's Content-Type, Cache-Control header and
// body content.
assertEquals("text/html; charset=ISO-8859-1",
response.getMimicState().getContentType());
assertArrayEquals(new String[] { "no-cache" },
response.getMimicState().getHeaders().getValues("Cache-Control"));
assertEquals("...expected result from dataManager.register...",
response.getMimicState().getBodyContentAsString());
}
}
Notes:
Each "mimic" has a "mimicState" object for its logical state. This provides a clear distinction between the Servlet API methods and the configuration and inspection of the mimic's internal state.
You might be surprised that the check of Content-Type includes "charset=ISO-8859-1". However, for the given "doPost" code this is as per the Servlet API Javadoc, and the HttpServletResponse's own getContentType method, and the actual Content-Type header produced on e.g. Glassfish 3. You might not realise this if using normal mock objects and your own expectations of the API's behaviour. In this case it probably doesn't matter, but in more complex cases this is the sort of unanticipated API behaviour that can make a bit of a mockery of mocks!
I've used response.getMimicState().getContentType() as the simplest way to check Content-Type and illustrate the above point, but you could indeed check for "text/html" on its own if you wanted (using response.getMimicState().getContentTypeMimeType()). Checking the Content-Type header the same way as for the Cache-Control header also works.
For this example the response content is checked as character data (with this using the Writer's encoding). We could also check that the response's Writer was used rather than its OutputStream (using response.getMimicState().isWritingCharacterContent()), but I've taken it that we're only concerned with the resulting output, and don't care what API calls produced it (though that could be checked too...). It's also possible to retrieve the response's body content as bytes, examine the detailed state of the Writer/OutputStream etc.
There are full details of ObMimic and a free download at the OpenBrace website. Or you can contact me if you have any questions (contact details are on the website).
EDIT: Cactus is now a dead project: http://attic.apache.org/projects/jakarta-cactus.html
You may want to look at cactus.
http://jakarta.apache.org/cactus/
Project Description
Cactus is a simple test framework for unit testing server-side java code (Servlets, EJBs, Tag Libs, Filters, ...).
The intent of Cactus is to lower the cost of writing tests for server-side code. It uses JUnit and extends it.
Cactus implements an in-container strategy, meaning that tests are executed inside the container.
Another approach would be to create an embedded server to "host" your servlet, allowing you to write calls against it with libraries meant to make calls to actual servers (the usefulness of this approach somewhat depends on how easily you can make "legitimate" programatic calls to the server - I was testing a JMS (Java Messaging Service) access point, for which clients abound).
There are a couple of different routes you can go - the usual two are tomcat and jetty.
Warning: something to be mindful of when choosing the server to embed is the version of servlet-api you are using (the library which provides classes like HttpServletRequest). If you are using 2.5, I found Jetty 6.x to work well (which is the example I'll give below). If you're using servlet-api 3.0, the tomcat-7 embedded stuff seems to be a good option, however I had to abandon my attempt to use it, as the application I was testing used servlet-api 2.5. Trying to mix the two will result in NoSuchMethod and other such exceptions when attempting to configure or start the server.
You can set up such a server like this (Jetty 6.1.26, servlet-api 2.5):
public void startServer(int port, Servlet yourServletInstance){
Server server = new Server(port);
Context root = new Context(server, "/", Context.SESSIONS);
root.addServlet(new ServletHolder(yourServletInstance), "/servlet/context/path");
//If you need the servlet context for anything, such as spring wiring, you coudl get it like this
//ServletContext servletContext = root.getServletContext();
server.start();
}
Use Selenium for webbased unit tests. There's a Firefox plugin called Selenium IDE which can record actions on the webpage and export to JUnit testcases which uses Selenium RC to run the test server.
First you should probably refactor this a bit so that the DataManager is not created in the doPost code.. you should try Dependency Injection to get an instance. (See the Guice video for a nice intro to DI.). If you're being told to start unit testing everything, then DI is a must-have.
Once your dependencies are injected you can test your class in isolation.
To actually test the servlet, there are other older threads that have discussed this.. try here and here.
public class WishServletTest {
WishServlet wishServlet;
HttpServletRequest mockhttpServletRequest;
HttpServletResponse mockhttpServletResponse;
#Before
public void setUp(){
wishServlet=new WishServlet();
mockhttpServletRequest=createNiceMock(HttpServletRequest.class);
mockhttpServletResponse=createNiceMock(HttpServletResponse.class);
}
#Test
public void testService()throws Exception{
File file= new File("Sample.txt");
File.createTempFile("ashok","txt");
expect(mockhttpServletRequest.getParameter("username")).andReturn("ashok");
expect(mockhttpServletResponse.getWriter()).andReturn(new PrintWriter(file));
replay(mockhttpServletRequest);
replay(mockhttpServletResponse);
wishServlet.doGet(mockhttpServletRequest, mockhttpServletResponse);
FileReader fileReader=new FileReader(file);
int count = 0;
String str = "";
while ( (count=fileReader.read())!=-1){
str=str+(char)count;
}
Assert.assertTrue(str.trim().equals("Helloashok"));
verify(mockhttpServletRequest);
verify(mockhttpServletResponse);
}
}