How can I add empty xmlns="" tag to header elements?
Let's imagine we have same project in two servers.
In this project I used the below SOAPHandler.
First server send request with empty xmlns="" tag<username xmlns="">test</username><password xmlns="">test</password>, but second server send request without xmlns="" tag.
<username>test</username><password>test</password>I need xmlns="" tag in every servers.
How can I solve this problem?
import java.util.Collections;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import org.apache.log4j.Logger;
/**
*
* #author BashirovMA
*/
public class MyHandler implements SOAPHandler<SOAPMessageContext> {
static final Logger log = Logger.getLogger(MyHandler.class);
private String username;
private String password;
public MyHandler() {
this.username = "";
this.password = "";
}
public MyHandler(String username, String password) {
this.username = username;
this.password = password;
}
public MyHandler(String username, String password) {
this.username = username;
this.password = password;
}
#Override
public boolean handleMessage(SOAPMessageContext smc) {
SOAPMessage msg = smc.getMessage();
Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outboundProperty.booleanValue()) {
try {
SOAPEnvelope envelope = smc.getMessage().getSOAPPart().getEnvelope();
if (envelope.getHeader() != null) {
envelope.getHeader().detachNode();
}
SOAPHeader header = envelope.addHeader();
SOAPElement root = header.addHeaderElement(envelope.createName("messageHeader", "", "http://services.ws.com/"));
SOAPElement el1 = root.addChildElement(envelope.createName("username", "", ""));
el1.setValue(String.valueOf(username));
SOAPElement el2 = root.addChildElement(envelope.createName("password", "", ""));
el2.setValue(String.valueOf(password));
msg.saveChanges();
} catch (Exception e) {
e.printStackTrace();
log.error(e);
}
} else {
try {
SOAPMessage message = smc.getMessage();
message.writeTo(System.out);
} catch (Exception ex) {
ex.printStackTrace();
log.error(ex);
}
}
return true;
}
#Override
public Set<QName> getHeaders() {
return null;
}
#Override
public boolean handleFault(SOAPMessageContext messageContext) {
return true;
}
#Override
public void close(MessageContext context) {
}
}
Related
I am implementing a module to take the screenshot of logged in user after every 3 minutes.
This module works fine
But the problem I am facing is that whenever i logged in the user the job starts as it intends to do, but on the logout I shuts down the scheduler. But now the next time i try to login back now scheduler initialized but job isn't starting. I need to redeploy project again for next run.
Here is my LoginBean.java class from where I am starting the job.
package com.viremp.beans;
import java.awt.AWTException;
import java.io.IOException;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.viremp.component.HandleHobs;
#ManagedBean
#SessionScoped
public class LoginBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = -8650636789236091591L;
private static Logger LOGGER = LoggerFactory.getLogger(LoginBean.class);
private String username;
private String password;
private String error;
private boolean visible = false;
private HandleHobs handleHobs;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public boolean isVisible() {
return visible;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
/*
* public LoginBean() { try { if (handleHobs != null &&
* !handleHobs.isJobStoredScreenShotIsStarted()) { handleHobs = new
* HandleHobs(); } } catch (Exception e) { LOGGER.error("error init job", e); }
*
* }
*/
#PostConstruct
public void init() {
try {
if (handleHobs == null || !handleHobs.isJobStoredScreenShotIsStarted()) {
handleHobs = new HandleHobs();
}
} catch (Exception e) {
LOGGER.error("error init job", e);
}
}
public void login() throws ClassNotFoundException, SQLException, IOException, AWTException {
// String un = "a";
// String pw = "b";
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext externalContext = context.getExternalContext();
HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
// Login login = new Login();
// boolean isLoggedIn = login.LoginUser(username, password);
try {
request.login(username, password);
handleHobs.startJobStoredScreenShot(username);
externalContext
.redirect(externalContext.getRequestContextPath() + "/faces/Success.xhtml?faces-redirect=true");
} catch (Exception e) {
FacesContext fc = FacesContext.getCurrentInstance();
this.error = getErrorParam(fc);
setVisible(true);
System.out.println("not equal.. " + error);
e.printStackTrace();
}
/*
*
* if (isLoggedIn) { System.out.println("equal"); externalContext
* .redirect(externalContext.getRequestContextPath() +
* "/faces/Success.xhtml?faces-redirect=true"); } else {
*
* FacesContext fc = FacesContext.getCurrentInstance(); this.error =
* getErrorParam(fc);
*
* setVisible(true); System.out.println("not equal.. " + error);
*
* }
*/
}
public String getErrorParam(FacesContext fc) {
Map<String, String> params = fc.getExternalContext().getRequestParameterMap();
return params.get("error1");
}
public logout(){
handleHobs.shutdownJobStoredScreenShot();
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
externalContext.invalidateSession();
externalContext.redirect(externalContext.getRequestContextPath() + "/faces/login.xhtml?faces-redirect=true");
}
And here is my HandleHobs.java class which is for handling job, [sorry for the wrong class name, it should be HandleJobs.java]
package com.viremp.component;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import static org.quartz.TriggerBuilder.newTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HandleHobs {
private static Logger LOGGER = LoggerFactory.getLogger(HandleHobs.class);
private static JobDetail job;
private static Scheduler scheduler;
String email;
public HandleHobs(String email) {
this.email = email;
}
private static Trigger trigger;
{
try {
if (job == null && scheduler == null && trigger == null) {
LOGGER.info("initializing job");
job = (JobDetail) newJob(JobStoredScreenShot.class).withIdentity("job1", "group1").build();
trigger = newTrigger().withIdentity("trigger1", "group1").startNow()
.withSchedule(simpleSchedule().withIntervalInSeconds(5).repeatForever()).build();
scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.scheduleJob(job, trigger);
LOGGER.info("init successsful");
}
} catch (Exception e) {
LOGGER.error("fail to init variables for job", e);
}
}
public HandleHobs() {
}
public void startJobStoredScreenShot(String email) {
try {
this.email = email;
JobStoredScreenShot jss = new JobStoredScreenShot();
jss.setEmail(email);
if (scheduler != null && !scheduler.isStarted()) {
Scheduler scheduler1 = new StdSchedulerFactory().getScheduler();
System.out.println("here..... " + email);
scheduler1.getContext().put("email", email);
System.out.println("and here..... " + email);
scheduler.start();
}
LOGGER.info("init successsful");
} catch (Exception e) {
LOGGER.error("fail to init job JobStoredScreenShot", e);
}
}
public void shutdownJobStoredScreenShot() {
try {
if (scheduler.isStarted()) {
scheduler.shutdown();
}
LOGGER.info("shutdown successsful");
} catch (Exception e) {
LOGGER.error("fail to init job JobStoredScreenShot", e);
}
}
public boolean isJobStoredScreenShotIsStarted() {
boolean isStarted = false;
try {
if (scheduler != null) {
isStarted = true;
}
} catch (Exception e) {
LOGGER.error("fail get isTarted", e);
}
return isStarted;
}
}
And here it is my JobStoredScreenShot.java class
package com.viremp.component;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.time.LocalDate;
import javax.imageio.ImageIO;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.SchedulerContext;
import com.viremp.core.domain.Screenshot;
import com.viremp.core.domain.User;
import com.viremp.core.repository.ScreenshotRepository;
import com.viremp.core.repository.UserRepository;
import com.viremp.core.repository.impl.ScreenshotRepositoryImpl;
import com.viremp.core.repository.impl.UserRepositoryImpl;
public class JobStoredScreenShot implements Job {
String email;
User user = new User();
public void setEmail(String Email) {
this.email = Email;
System.out.println("in job stored class email is: " + email);
user.setEmail(email);
}
#Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {
try {
SchedulerContext schedulerContext = arg0.getScheduler().getContext();
// Below line gets the value from context.
// Just get it and cast it in to correct type
String email = (String) schedulerContext.get("email");
System.out.println(email);
BufferedImage image = new Robot()
.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "png", baos);
baos.flush();
byte[] imageInByte = baos.toByteArray();
baos.close();
System.out.println("in execute " + user.getEmail() + ".................: " + email);
UserRepository userRepository = new UserRepositoryImpl();
user = userRepository.getUserByEmail(email);
System.out.println("USER IS: " + user.getUsername() + " id is : " + user.getId());
// byte[] buffer = (((DataBufferByte)
// (image).getRaster().getDataBuffer()).getData());
InputStream inputStream = new ByteArrayInputStream(imageInByte);
LocalDate localDate = LocalDate.now();
Screenshot screenshot = new Screenshot();
screenshot.setInput(inputStream);
screenshot.setScreenshotName(user.getUsername());
screenshot.setUser(new User());
screenshot.getUser().setId(user.getId());
screenshot.setScreenShotTime(java.sql.Date.valueOf(localDate));
System.out.println("id is " + 1l);
ScreenshotRepository screenshotRepository = new ScreenshotRepositoryImpl();
screenshotRepository.create(screenshot);
ImageIO.write(image, "png", new File("d:\\screenshot.png"));
System.out.println("screenshot taken");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Please Help, Thanks
I have solved this issue by making job and scheduler null after shutting down the scheduler.
Here is the working code of HandleHobs.java
package com.viremp.component;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import static org.quartz.TriggerBuilder.newTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HandleHobs {
private static Logger LOGGER = LoggerFactory.getLogger(HandleHobs.class);
private static JobDetail job;
private static Scheduler scheduler;
String email;
// SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
public HandleHobs(String email) {
this.email = email;
}
private static Trigger trigger;
{
try {
LOGGER.info("initializing job");
job = (JobDetail) newJob(JobStoredScreenShot.class).withIdentity("job1", "group1").build();
trigger = newTrigger().withIdentity("trigger1", "group1").startNow()
.withSchedule(simpleSchedule().withIntervalInSeconds(5).repeatForever()).build();
scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.scheduleJob(job, trigger);
LOGGER.info("init successsful 1");
} catch (Exception e) {
LOGGER.error("fail to init variables for job", e);
}
}
public HandleHobs() {
}
public void startJobStoredScreenShot(String email) {
try {
System.out.println("yaar ma aa gaya hun");
this.email = email;
JobStoredScreenShot jss = new JobStoredScreenShot();
jss.setEmail(email);
if (scheduler != null && !scheduler.isStarted()) {
Scheduler scheduler1 = new StdSchedulerFactory().getScheduler();
System.out.println("here..... " + email);
scheduler1.getContext().put("email", email);
System.out.println("and here..... " + email);
scheduler.start();
}
LOGGER.info("init successsful");
} catch (Exception e) {
LOGGER.error("fail to init job JobStoredScreenShot", e);
}
}
public void shutdownJobStoredScreenShot() {
try {
if (scheduler.isStarted()) {
// JobExecutionContext context = new JobExecutionContext();
// JobKey key = context.getJobDetail().getKey();
// String jobId = key.getName();
// System.out.println("```````````````````NAME``````````````````````" + jobId);
// flag = true;
scheduler.shutdown();
scheduler = null; //i made it null here
job = null; // i made it null here
}
LOGGER.info("shutdown successsful");
} catch (Exception e) {
LOGGER.error("fail to init job JobStoredScreenShot", e);
}
}
public boolean isJobStoredScreenShotIsStarted() {
boolean isStarted = false;
try {
if (scheduler != null) {
isStarted = true;
}
} catch (Exception e) {
LOGGER.error("fail get isTarted", e);
}
return isStarted;
}
}
And this is my LoginBean.java from where I am initiating the job.
package com.viremp.beans;
import java.awt.AWTException;
import java.io.IOException;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.viremp.component.HandleHobs;
#ManagedBean
#SessionScoped
public class LoginBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = -8650636789236091591L;
private static Logger LOGGER = LoggerFactory.getLogger(LoginBean.class);
private String username;
private String password;
private String error;
private boolean visible = false;
private HandleHobs handleHobs;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public boolean isVisible() {
return visible;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
/*
* public LoginBean() { try { if (handleHobs != null &&
* !handleHobs.isJobStoredScreenShotIsStarted()) { handleHobs = new
* HandleHobs(); } } catch (Exception e) { LOGGER.error("error init job", e); }
*
* }
*/
#PostConstruct
public void init() {
try {
handleHobs = new HandleHobs();
} catch (Exception e) {
LOGGER.error("error init job", e);
}
}
public void login() throws ClassNotFoundException, SQLException, IOException, AWTException {
// String un = "a";
// String pw = "b";
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext externalContext = context.getExternalContext();
HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
// Login login = new Login();
// boolean isLoggedIn = login.LoginUser(username, password);
try {
request.login(username, password);
handleHobs.startJobStoredScreenShot(username);
externalContext
.redirect(externalContext.getRequestContextPath() + "/faces/Success.xhtml?faces-redirect=true");
} catch (Exception e) {
FacesContext fc = FacesContext.getCurrentInstance();
this.error = getErrorParam(fc);
setVisible(true);
System.out.println("not equal.. " + error);
e.printStackTrace();
}
/*
*
* if (isLoggedIn) { System.out.println("equal"); externalContext
* .redirect(externalContext.getRequestContextPath() +
* "/faces/Success.xhtml?faces-redirect=true"); } else {
*
* FacesContext fc = FacesContext.getCurrentInstance(); this.error =
* getErrorParam(fc);
*
* setVisible(true); System.out.println("not equal.. " + error);
*
* }
*/
}
public void logout() {
System.out.println("in logotu");
handleHobs.shutdownJobStoredScreenShot();
this.handleHobs = null; // here i also made null
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
externalContext.invalidateSession();
try {
externalContext
.redirect(externalContext.getRequestContextPath() + "/faces/Login.xhtml?faces-redirect=true");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public String getErrorParam(FacesContext fc) {
Map<String, String> params = fc.getExternalContext().getRequestParameterMap();
return params.get("error1");
}
}
Actually after shutting down the jobs did shutdown the scheduler but did not empty the job and scheduler, so on next login the scheduler and job keeps the value so that the job was not starting again, so i just made the values null on shutdown.
I am new to the SOAP world.
I have coverted the wsdl file to java class using maven plugin
Below is the pom.xml configuration.
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>3.1.12</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${project.basedir}/src/main/java</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>${project.basedir}/src/main/resources/EIAproxy.wsdl</wsdl>
<wsdlLocation>classpath:EIAproxy.wsdl</wsdlLocation>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
below is the class files
Interface definition
#WebService(targetNamespace = "http://schema.concierge.com", name = "EaiEnvelopeSoap")
#XmlSeeAlso({com.concierge.schema.envelope.ObjectFactory.class, ObjectFactory.class})
#SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface EaiEnvelopeSoap {
#WebResult(name = "clientRequestResponse", targetNamespace = "http://schema.concierge.com", partName = "parameters")
#WebMethod(action = "http://www.openuri.org/clientRequest")
public ClientRequestResponse clientRequest(
#WebParam(partName = "parameters", name = "clientRequest", targetNamespace = "http://schema.concierge.com")
ClientRequest parameters
);
}
Here is class file that extends service
#WebServiceClient(name = "EaiEnvelope",
wsdlLocation = "classpath:EIAproxy.wsdl",
targetNamespace = "http://schema.concierge.com")
public class EaiEnvelope extends Service {
public final static URL WSDL_LOCATION;
public final static QName SERVICE = new QName("http://schema.concierge.com", "EaiEnvelope");
public final static QName EaiEnvelopeSoap = new QName("http://schema.concierge.com", "EaiEnvelopeSoap");
static {
URL url = EaiEnvelope.class.getClassLoader().getResource("EIAproxy.wsdl");
if (url == null) {
java.util.logging.Logger.getLogger(EaiEnvelope.class.getName())
.log(java.util.logging.Level.INFO,
"Can not initialize the default wsdl from {0}", "classpath:EIAproxy.wsdl");
}
WSDL_LOCATION = url;
}
public EaiEnvelope(URL wsdlLocation) {
super(wsdlLocation, SERVICE);
}
public EaiEnvelope(URL wsdlLocation, QName serviceName) {
super(wsdlLocation, serviceName);
}
public EaiEnvelope() {
super(WSDL_LOCATION, SERVICE);
}
public EaiEnvelope(WebServiceFeature ... features) {
super(WSDL_LOCATION, SERVICE, features);
}
public EaiEnvelope(URL wsdlLocation, WebServiceFeature ... features) {
super(wsdlLocation, SERVICE, features);
}
public EaiEnvelope(URL wsdlLocation, QName serviceName, WebServiceFeature ... features) {
super(wsdlLocation, serviceName, features);
}
/**
*
* #return
* returns EaiEnvelopeSoap
*/
#WebEndpoint(name = "EaiEnvelopeSoap")
public EaiEnvelopeSoap getEaiEnvelopeSoap() {
return super.getPort(EaiEnvelopeSoap, EaiEnvelopeSoap.class);
}
/**
*
* #param features
* A list of {#link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the <code>features</code> parameter will have their default values.
* #return
* returns EaiEnvelopeSoap
*/
#WebEndpoint(name = "EaiEnvelopeSoap")
public EaiEnvelopeSoap getEaiEnvelopeSoap(WebServiceFeature... features) {
return super.getPort(EaiEnvelopeSoap, EaiEnvelopeSoap.class, features);
}
}
My SoapHandler file is
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringWriter;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import com.xxx.fdp.common.LoggerManager;
import com.xxx.fdp.constants.LoggerConstantEnum;
import com.xxx.fdp.property.config.AbilityConfig;
public class HeaderHandler implements SOAPHandler<SOAPMessageContext> {
/** The logger manager. */
LoggerManager loggerManager = new LoggerManager();
#Override
public boolean handleMessage(SOAPMessageContext smc) {
Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp, "Entered in handleMessage with outBoundProperty : " + outboundProperty);
if (outboundProperty.booleanValue()) {
SOAPMessage message = smc.getMessage();
loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp, " Message : " + message);
try {
message.writeTo(System.out);
SOAPEnvelope envelope = smc.getMessage().getSOAPPart().getEnvelope();
envelope.addNamespaceDeclaration("com", "http://schema.concierge.com");
message.getMimeHeaders().setHeader("Content-Type", "application/soap+xml; charset=utf-8");
SOAPHeader header = envelope.addHeader();
SOAPElement authentication = header.addChildElement("authentication", "auth", "http://schemas.eia.org/middleware/AuthInfo");
SOAPElement username = authentication.addChildElement("user", "auth");
username.addTextNode(AbilityConfig.getInstance().getSoapUser());
SOAPElement password = authentication.addChildElement("password", "auth");
password.addTextNode(AbilityConfig.getInstance().getSoapPassword());
SOAPElement authType = authentication.addChildElement("type", "auth");
authType.addTextNode(AbilityConfig.getInstance().getSoapAuthType());
SOAPBody body = envelope.getBody();
// Print out the outbound SOAP message to System.out
message.saveChanges();
loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp, "Request Format : " + envelope.getBody() + ",Header : " + envelope.getHeader());
ByteArrayOutputStream out = new ByteArrayOutputStream();
message.writeTo(out);
String strMsg = new String(out.toByteArray());
loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp, "Request Format Message: " + strMsg);
StringWriter writer = new StringWriter();
message.writeTo(new StringOutputStream(writer));
// message.writeTo(System.out);
System.out.println("");
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
// This handler does nothing with the response from the Web
// Service so
// we just print out the SOAP message.
SOAPMessage message = smc.getMessage();
loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp, "Response Message : " + message);
message.writeTo(System.out);
System.out.println("");
} catch (Exception ex) {
ex.printStackTrace();
}
}
loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp, "Exit in handleMessage with outBoundProperty : " + outboundProperty);
return outboundProperty;
}
private static class StringOutputStream extends OutputStream {
private StringWriter writer;
public StringOutputStream(StringWriter writer) {
this.writer = writer;
}
#Override
public void write(int b) throws IOException {
writer.write(b);
}
}
#Override
public boolean handleFault(SOAPMessageContext context) {
loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp, "Entered in handleFault ");
return false;
}
#Override
public void close(MessageContext context) {
loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp, "Entered in close ");
}
#Override
public Set<QName> getHeaders() {
// TODO Auto-generated method stub
return null;
}
}
My handlerResolver file is
import java.util.ArrayList;
import java.util.List;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.handler.PortInfo;
import com.xxx.fdp.common.LoggerManager;
import com.xxx.fdp.constants.LoggerConstantEnum;
public class HeaderHandlerResolver implements HandlerResolver {
LoggerManager loggerManager = new LoggerManager();
#SuppressWarnings("rawtypes")
#Override
public List<Handler> getHandlerChain(PortInfo portInfo) {
loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp,"Entered in getHandlerChain");
List<Handler> handlerChain = new ArrayList<Handler>();
loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp,"Created handlerChanin object");
HeaderHandler headerHandler = new HeaderHandler();
loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp,"Created HeaderHandler object");
handlerChain.add(headerHandler);
loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp,"returned handlerChain");
return handlerChain;
}
}
Method which is used to call service
public void processRequest(EaiEnvelope envelope,AbilitySyncUpData abilityObject) {
loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp, "| processing ability async up starts with TranactionId : "+abilityObject.getTransactionId());
try {
com.concierge.schema.EaiEnvelope service=new com.concierge.schema.EaiEnvelope();
HeaderHandlerResolver handlerResolver = new HeaderHandlerResolver();
service.setHandlerResolver(handlerResolver);
EaiEnvelopeSoap port=service.getEaiEnvelopeSoap();
ClientRequest request=new ClientRequest();
request.setEaiEnvelope(envelope);
loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp,"Sending request to web service with TranactionId : "+abilityObject.getTransactionId());
ClientRequestResponse response=port.clientRequest(request);
loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp,"Response received "+response+" After sending request to web service with TranactionId : "+abilityObject.getTransactionId());
} catch (Exception e) {
loggerManager.error(LoggerConstantEnum.AbilityDailySyncUp, "| Exception occured : " + e.fillInStackTrace(), e);
writeCsvFile(abilityObject);
}
loggerManager.info(LoggerConstantEnum.AbilityDailySyncUp, "| processRequest method ends here with TranactionId : "+abilityObject.getTransactionId());
I am not able to get call in soapHandler's handleMessage method
and call is going on getHeadersmethod when the service methodClientRequestResponse response=port.clientRequest(request);` is called.
I have reffered from several answers that are present on stackoverflow:
SoapHandler not called after WS operation is executed
https://stackoverflow.com/a/12712728/1569443
https://stackoverflow.com/a/14523921/1569443
http://www.javadb.com/using-a-message-handler-to-alter-the-soap-header-in-a-web-service-client/
https://soa2world.blogspot.com/2009/05/direct-web-service-client-using-java.html
I am still not able to call handleMessage method of handler as no logs gets printed. Call is made in handlerResolver class but not in HeaderHandler class.
How can I resolve this issue?
I'm trying to setup a SOAPHandler on my server to convert this incoming request
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<getMachine xmlns="http://machine.soap.webservices.product.company.at/">
<machineId>92623-15853588</machineId>
</getMachine>
</S:Body>
</S:Envelope>
to this request.
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<enns1:getMachine xmlns:enns1="http://machine.soap.webservices.product.company.at/">
<machineId>92623-15853588</machineId>
</enns1:getMachine>
</S:Body>
</S:Envelope>
My SOAPHandler looks like this.
package at.company.product.webservices.soap;
import java.io.IOException;
import java.util.Iterator;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
public class SOAPValidationHandler implements SOAPHandler<SOAPMessageContext> {
private static final String PREFIX = "enns1";
#Override
public boolean handleMessage(SOAPMessageContext context) {
System.out.println("Server : handleMessage()......");
Boolean isRequest = (Boolean) context
.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
// inbound
if (!isRequest) {
try {
SOAPMessage soapMsg = context.getMessage();
SOAPBody body = soapMsg.getSOAPBody();
Iterator<SOAPElement> it = body.getChildElements();
// Look for all body elements who have a "xmlns" attribute and
// add a namespace prefix to it
while (it.hasNext()) {
SOAPElement elem = it.next();
addNamespacePrefix(elem);
Iterator itChildren = elem.getChildElements();
while (itChildren.hasNext()) {
Object child = itChildren.next();
if (child instanceof SOAPElement) {
SOAPElement cElem = ((SOAPElement) child);
// TODO: Remove the namespace from the child
// cElem.removeNamespaceDeclaration(""); => Does not
// work
}
}
}
// tracking
soapMsg.writeTo(System.out);
} catch (SOAPException e) {
System.err.println(e);
} catch (IOException e) {
System.err.println(e);
}
}
return true;
}
private void addNamespacePrefix(SOAPElement elem) throws SOAPException {
Iterator<Object> it = elem.getAllAttributes();
QName name = new QName("xmlns");
String value = elem.getAttributeValue(name);
if (value != null) {
elem.addNamespaceDeclaration(PREFIX, elem.getNamespaceURI());
elem.removeNamespaceDeclaration("");
elem.setPrefix(PREFIX);
}
}
#Override
public boolean handleFault(SOAPMessageContext context) {
System.out.println("Server : handleFault()......");
return true;
}
#Override
public void close(MessageContext context) {
System.out.println("Server : close()......");
}
#Override
public Set<QName> getHeaders() {
System.out.println("Server : getHeaders()......");
return null;
}
}
After the processing of the request with the SOAPHandler the request looks like this:
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<enns1:getMachine xmlns:enns1="http://machine.soap.webservices.product.company.at/">
<machineId xmlns="http://machine.soap.webservices.product.company.at/">92623-15853588</machineId>
</enns1:getMachine>
</S:Body>
</S:Envelope>
As you can see I'm able to add the namespace prefix to the <getMachine> tag but then it automatically adds the xmlns attribute to the child element <machineId>. How can I avoid or fix this?
After toying around with the API I came up with this solution. This solves the described case.
package at.company.product.webservices.soap;
import java.io.IOException;
import java.util.Iterator;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import javax.xml.ws.soap.SOAPFaultException;
public class SOAPValidationHandler implements SOAPHandler<SOAPMessageContext> {
private static final String PREFIX = "enns1";
#Override
public boolean handleMessage(SOAPMessageContext context) {
Boolean isRequest = (Boolean) context
.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
// for response message only, true for outbound messages, false for
// inbound
if (!isRequest) {
try {
SOAPMessage soapMsg = context.getMessage();
SOAPEnvelope soapEnv = soapMsg.getSOAPPart().getEnvelope();
SOAPHeader soapHeader = soapEnv.getHeader();
// if no header, add one
if (soapHeader == null) {
soapHeader = soapEnv.addHeader();
// throw exception
generateSOAPErrMessage(soapMsg, "No SOAP header.");
}
SOAPBody body = soapMsg.getSOAPBody();
Iterator<SOAPElement> it = body.getChildElements();
while (it.hasNext()) {
SOAPElement elem = it.next();
addNamespacePrefix(elem);
Iterator itChildChildren = elem.getChildElements();
while (itChildChildren.hasNext()) {
Object obj = itChildChildren.next();
if ((obj instanceof SOAPElement)) {
SOAPElement soapElem = (SOAPElement) obj;
String name = soapElem.getElementName().getLocalName();
QName qName = new QName(name);
((SOAPElement) obj).setElementQName(qName);
}
}
}
// tracking
soapMsg.writeTo(System.out);
} catch (SOAPException e) {
System.err.println(e);
} catch (IOException e) {
System.err.println(e);
}
}
// continue other handler chain
return true;
}
private void addNamespacePrefix(SOAPElement elem) throws SOAPException {
Iterator<Object> it = elem.getAllAttributes();
QName name = new QName("xmlns");
String value = elem.getAttributeValue(name);
if (value != null) {
elem.addNamespaceDeclaration(PREFIX, elem.getNamespaceURI());
elem.removeNamespaceDeclaration("");
elem.setPrefix(PREFIX);
}
}
#Override
public boolean handleFault(SOAPMessageContext context) {
return true;
}
#Override
public void close(MessageContext context) {
}
#Override
public Set<QName> getHeaders() {
return null;
}
private void generateSOAPErrMessage(SOAPMessage msg, String reason) {
try {
SOAPBody soapBody = msg.getSOAPPart().getEnvelope().getBody();
SOAPFault soapFault = soapBody.addFault();
soapFault.setFaultString(reason);
throw new SOAPFaultException(soapFault);
} catch (SOAPException e) {
}
}
}
The application published by hmkcode.com takes some data from user and parse & convert, and send to a java servlet called jsonservlet. I changed the input values parsed but I'm receiving everytime NullPointerException.
java.lang.NullPointerException
java.io.StringReader.<init>(StringReader.java:50)
com.fasterxml.jackson.core.JsonFactory.createParser(JsonFactory.java:796)
com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)
iaau.uimsmobile.getData.getDataServlet.doPost(getDataServlet.java:48)
iaau.uimsmobile.getData.getDataServlet.doGet(getDataServlet.java:65)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
LogCat trace
02-01 10:31:38.232 424-424/com.iaaum D/dalvikvm﹕ GC_EXTERNAL_ALLOC freed 81K, 52% free 2630K/5379K, external 904K/1038K, paused 72ms
02-01 10:32:03.392 424-424/com.iaaum W/KeyCharacterMap﹕ No keyboard for id 0
02-01 10:32:03.392 424-424/com.iaaum W/KeyCharacterMap﹕ Using default keymap: /system/usr/keychars/qwerty.kcm.bin
02-01 10:32:08.962 424-433/com.iaaum D/InputStream﹕ Connection to http://localhost:8080 refused
02-01 10:34:28.142 424-434/com.iaaum D/InputStream﹕ Connection to http://localhost:8080 refused
At last, I changed the strings in JSON format inside the toString() methods in both sides. The failure what #SotiriosDelimanolis talked about is appeared.
com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input
at [Source: java.io.StringReader#30b3b5; line: 1, column: 1]
com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:2931)
com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2873)
com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)
iaau.uimsmobile.getData.getDataServlet.doPost(getDataServlet.java:48)
iaau.uimsmobile.getData.getDataServlet.doGet(getDataServlet.java:65)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
Client side --> User.java
public class User{
private String IDnumber;
private String Password;
public String getIDnumber() {
return IDnumber;
}
public void setIDnumber(String IDnumber) {
this.IDnumber = IDnumber;
}
public String getPassword() {
return Password;
}
public void setPassword(String password) {
Password = password;
}
#Override
public String toString()
{
// { "IDnumber":"" , "Password":"" }
return "{\"IDnumber\":"+"\""+IDnumber+"\""+",\"Password\":"+"\""+Password+"\"}";
}
}
Client side --> LoginActivity.java
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
import android.widget.Toast;
import com.iaaum.user.User;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class LoginActivity extends Activity implements OnClickListener
{
TextView IsConnected;
EditText id_number;
EditText password;
Button sign_button;
User current_user;
public String urlAddress = "http://192.168.1.101:8080/UIMSMobile/getDataServlet";
//public String urlAddress = "http://127.0.0.1:8080/UIMSMobile/getDataServlet";
//public String urlAddress = "http://localhost:8080/UIMSMobile/getDataServlet";
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_login);
// get reference to the views
IsConnected = (TextView) findViewById(R.id.isConnected);
id_number = (EditText) findViewById(R.id.id_number);
password = (EditText) findViewById(R.id.password);
sign_button= (Button) findViewById(R.id.sign_in_button);
// check if you are connected or not
if(IsConnectedMethod())
{
IsConnected.setBackgroundColor(0xFF00CC00);
IsConnected.setText("You are connected");
}
else{
IsConnected.setText("You are NOT connected");
}
// add click listener to Button "POST"
sign_button.setOnClickListener(this);
}
#Override
public void onClick(View view)
{
switch(view.getId()){
case R.id.sign_in_button:
if(!validate())
Toast.makeText(getBaseContext(), "Enter some data!", Toast.LENGTH_LONG).show();
// call AsyncTask to perform network operation on separate thread
new HttpAsyncTask().execute(urlAddress);
break;
}
}
public boolean IsConnectedMethod()
{
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Activity.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return networkInfo != null && networkInfo.isConnected();
}
public static String Post(String url, User current_user)
{
InputStream inputStream = null;
String result = "";
try
{
// 1. create HttpClient
HttpClient httpclient = new DefaultHttpClient();
// 2. make POST request to the given URL
HttpPost httpPost = new HttpPost(url);
String json = "";
// 3. build jsonObject
JSONObject jsonObject = new JSONObject();
jsonObject.accumulate("IDnumber", current_user.getIDnumber());
jsonObject.accumulate("Password", current_user.getPassword());
// 4. convert JSONObject to JSON in String
json = jsonObject.toString();
// ** Alternative way to convert Person object to JSON string using Jackson Lib
// ObjectMapper mapper = new ObjectMapper();
// json = mapper.writeValueAsString(person);
// 5. set json to StringEntity
StringEntity se = new StringEntity(json);
// 6. set httpPost Entity
httpPost.setEntity(se);
// 7. Set some headers to inform server about the type of the content
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
// 8. Execute POST request to the given URL
HttpResponse httpResponse = httpclient.execute(httpPost);
// 9. receive response as inputStream
inputStream = httpResponse.getEntity().getContent();
// 10. convert inputstream to string
if(inputStream != null)
result = convertInputStreamToString(inputStream);
else
result = "Did not work!";
} catch (Exception e) {
Log.d("InputStream", e.getLocalizedMessage());
}
// 11. return result
return result;
}
private class HttpAsyncTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls)
{
current_user = new User();
current_user.setIDnumber(id_number.getText().toString());
current_user.setPassword(password.getText().toString());
return Post(urls[0], current_user);
}
// onPostExecute displays the results of the AsyncTask.
#Override
protected void onPostExecute(String result) {
Toast.makeText(getBaseContext(), "Data Sent!", Toast.LENGTH_LONG).show();
}
}
private boolean validate()
{
if(id_number.getText().toString().trim().equals(""))
return false;
else return !password.getText().toString().trim().equals("");
}
private static String convertInputStreamToString(InputStream inputStream) throws IOException {
BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(inputStream));
String line = "";
String result = "";
while((line = bufferedReader.readLine()) != null)
result += line;
inputStream.close();
return result;
}
}
Client side --> AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.iaaum" >
<uses-sdk
android:minSdkVersion="8"
android:maxSdkVersion="19"
/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.iaaum.LoginActivity"
android:label="#string/title_activity_login" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Server side --> User.java
public class User
{
private String idnumber;
private String password;
public User(String idnumber, String password) {
this.idnumber = idnumber;
this.password = password;
}
public String getIDnumber() {
return idnumber;
}
public void setIDnumber(String idnumber) {
this.idnumber = idnumber;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#Override
public String toString()
{
return "{\"IDnumber\":"+"\""+idnumber+"\""+",\"Password\":"+"\""+password+"\"}";
}
}
Server side --> getDataServlet.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
public class getDataServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
// This will store all received articles
List<User> _users = new LinkedList<User>();
/***************************************************
* URL: /getDataServlet
* doPost(): receives JSON data, parse it, map it and send back as JSON
* #param request
* #param response
* #throws javax.servlet.ServletException
* #throws java.io.IOException
****************************************************/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
// 1. get received JSON data from request
BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
String json = "";
if(br.readLine() != null)
{
json = br.readLine();
}
// 2. initiate jackson mapper
ObjectMapper mapper = new ObjectMapper();
// 3. Convert received JSON to User
User _user = mapper.readValue(json, User.class);
// 4. Set response type to JSON
response.setContentType("application/json");
// 5. Add article to List<Article>
_users.add(_user);
// 6. Send List<Article> as JSON to client
mapper.writeValue(response.getOutputStream(), _users);
}
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
doPost(request, response);
}
#Override
public String getServletInfo()
{
return "Short description";
}
}
The only way that exception could be thrown is if the String json you pass in
mapper.readValue(json, User.class);
is null.
You're doing something wrong here
if(br != null)
{
json = br.readLine();
}
br could never be null there. Maybe you meant
String temp;
if ((temp = br.readLine()) != null)
{
json = temp;
}
Or even better, pass the stream directly to one of the ObjectMapper's overloaded readValue(..) methods and handle any errors.
In any case, it seems you aren't sending anything in the body of the request, so readLine() returns null which you assign to json and that causes a failure in the ObjectMapper.
Your doGet() is delegating to your doPost(). Is it possible you are sending GET requests?
By handling your suggessions, I made some changes in codes and the application is working now. Here is the changes:
Server Side ---> getDataServlet.java
package com.****;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.****.dao.User;
public class getDataServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
List<User> users = new LinkedList<User>();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
String json = "";
if(br != null){
json = br.readLine();}
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(json, User.class);
response.setContentType("application/json");
if(users.size() > 20){
users.remove(0);}
users.add(user);
mapper.writeValue(response.getOutputStream(), users);
}
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
ObjectMapper mapper = new ObjectMapper();
resp.setContentType("application/json");
mapper.writeValue(resp.getOutputStream(), users);
}
}
Server Side --> User.java
package com.*****.dao;
public class User {
private String idnumber;
private String password;
public String getIdnumber() {
return idnumber;
}
public void setIdnumber(String idnumber) {
this.idnumber = idnumber;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#Override
public String toString() {
return "User [idnumber=" + idnumber + ", password=" + password + "]";
}
}
Client Side ---> MainActivity.java
JSONObject jsonObject = new JSONObject();
jsonObject.accumulate("idnumber", user.getIdnumber());
jsonObject.accumulate("password", user.getPassword());
Client Side ---> User.java
#Override
public String toString()
{
return "User [idnumber=" + idnumber + ", password=" + password + "]";
}
And after post data output appeared:
[{"idnumber":"987654321 ","password":"123456789"}]
Solution 1:
May be its problem of you given URL, if you working on localhost then use your IP Address instead of localhost
you can check your IP in command prompt using ipconfig command.
Solution 2:
In your User.java You may have to use JSONObject and JSONArray to create JSON String in toString() method.
I try to invoke HTTPS SOAP web service through java code:
URL url = new URL("https://somehost:8181/services/"SomeService?wsdl");
QName qname = new QName("http://services.somehost.com/", "SomeService");
Service service = Service.create(url, qname);
SomeService port = service.getPort(SomeService .class);
port.doSomething();
But get exception:
threw an unexpected exception: javax.xml.ws.soap.SOAPFaultException: Security Requirements not met - No Security header in message
When I analized correct request sample I determined it have to contain header:
<S:Header>
<To xmlns="http://www.w3.org/2005/08/addressing">http://somehost:8181/services/SomeService</To>
<Action xmlns="http://www.w3.org/2005/08/addressing">https://somehost:8181/services/"SomeService/doSomethingRequest</Action>
<ReplyTo xmlns="http://www.w3.org/2005/08/addressing">
<Address>http://www.w3.org/2005/08/addressing/anonymous</Address>
</ReplyTo>
<MessageID xmlns="http://www.w3.org/2005/08/addressing">uuid:3428539e-d645-72ae-adc0-5423c1e68942</MessageID>
<wsse:Security S:mustUnderstand="true">
<wsu:Timestamp wsu:Id="_1" xmlns:ns14="http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512" xmlns:ns13="http://schemas.xmlsoap.org/soap/envelope/">
<wsu:Created>2013-01-15T16:36:30Z</wsu:Created>
<wsu:Expires>2014-01-15T14:06:30Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
So how to add this header to my SOAP request?
I personally add two classes: HeaderHandler and HeaderHandlerResolver:
import java.util.HashSet;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
public class HeaderHandler implements SOAPHandler<SOAPMessageContext> {
public boolean handleMessage(SOAPMessageContext smc) {
Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outboundProperty.booleanValue()) {
SOAPMessage message = smc.getMessage();
try {
SOAPEnvelope envelope = smc.getMessage().getSOAPPart().getEnvelope();
SOAPHeader header = envelope.addHeader();
SOAPElement security =
header.addChildElement("Security", "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
SOAPElement usernameToken =
security.addChildElement("UsernameToken", "wsse");
usernameToken.addAttribute(new QName("xmlns:wsu"), "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
SOAPElement username =
usernameToken.addChildElement("Username", "wsse");
username.addTextNode("test");
SOAPElement password =
usernameToken.addChildElement("Password", "wsse");
password.setAttribute("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
password.addTextNode("test321");
//Print out the outbound SOAP message to System.out
message.writeTo(System.out);
System.out.println("");
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
//This handler does nothing with the response from the Web Service so
//we just print out the SOAP message.
SOAPMessage message = smc.getMessage();
message.writeTo(System.out);
System.out.println("");
} catch (Exception ex) {
ex.printStackTrace();
}
}
return outboundProperty;
}
public Set getHeaders() {
// The code below is added on order to invoke Spring secured WS.
// Otherwise,
// http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd
// won't be recognised
final QName securityHeader = new QName(
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
"Security", "wsse");
final HashSet headers = new HashSet();
headers.add(securityHeader);
return headers;
}
public boolean handleFault(SOAPMessageContext context) {
//throw new UnsupportedOperationException("Not supported yet.");
return true;
}
public void close(MessageContext context) {
//throw new UnsupportedOperationException("Not supported yet.");
}
}
And
import java.util.ArrayList;
import java.util.List;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.handler.PortInfo;
public class HeaderHandlerResolver implements HandlerResolver {
public List<Handler> getHandlerChain(PortInfo portInfo) {
List<Handler> handlerChain = new ArrayList<Handler>();
HeaderHandler hh = new HeaderHandler();
handlerChain.add(hh);
return handlerChain;
}
}
In the HeaderHandler class, you can add needed credentials.
To use them finally:
HeaderHandlerResolver handlerResolver = new HeaderHandlerResolver();
service.setHandlerResolver(handlerResolver);
I have followed the steps mentioned by #LaabidiRaissi. The code works fine but it never appends the security element under the header. I have confirmed it by printing out the outbound SOAP message to System.out. After a deep research, I have found that the SOAPMessage needs to be explicitly saved for reflecting the updated message header.
soapMessage.saveChanges();
For more reference -
Check this link
Sample main Class:
package test;
import java.util.ArrayList;
import java.util.List;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.handler.Handler;
// next headers is generated from "NetBeans New Webservice Client"
import sk.firma.wstest.definitions.*;
import sk.firma.wstest.schemas.*;
/**
*
* #author Jan
*/
public class TestWSService {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
try {
WsService service = new WsService();
Ws port = service.getWsKsSoap11();
// This is the block that apply the Ws Security to the request
BindingProvider bindingProvider = (BindingProvider) port;
#SuppressWarnings("rawtypes")
List<Handler> handlerChain = new ArrayList<Handler>();
handlerChain.add(new WSSecurityHeaderSOAPHandler("username", "password"));
bindingProvider.getBinding().setHandlerChain(handlerChain);
// Initialize and Run Service
InVal inVal = new InVal();
ReturnValue retVal = port.test(inVal);
} catch (Exception e) {
e.printStackTrace();
}
}
}
And now WS-Security Header SOAP Handler:
package test;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.TimeZone;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPHeader;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
public class WSSecurityHeaderSOAPHandler implements SOAPHandler<SOAPMessageContext> {
private static final String URL_WSSE_NAMESPACE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
private static final String URL_WSU_NAMESPACE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
private final String usernameText;
private final String passwordText;
public WSSecurityHeaderSOAPHandler(String usernameText, String passwordText) {
this.usernameText = usernameText;
this.passwordText = passwordText;
}
public String getCurrentDateTime() {
/* e.g. 2001-10-13T09:00:00Z */
final SimpleDateFormat FORMATTER_DATETIME_NO_MS = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
DateFormat dfETC = FORMATTER_DATETIME_NO_MS;
dfETC.setTimeZone(TimeZone.getTimeZone("CET"));
StringBuffer dateETC = new StringBuffer(dfETC.format(new Date()));
dateETC.append('Z');
return dateETC.toString();
}
public String getCurrentDateTimePlusDelay(long delayInSeconds) {
/* e.g. 2001-10-13T09:00:00Z */
final SimpleDateFormat FORMATTER_DATETIME_NO_MS = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
DateFormat dfETC = FORMATTER_DATETIME_NO_MS;
dfETC.setTimeZone(TimeZone.getTimeZone("CET"));
Date date = new Date();
long timeInMsecs = date.getTime();
date.setTime(timeInMsecs + delayInSeconds*1000L);
StringBuffer dateETC = new StringBuffer(dfETC.format(date));
dateETC.append('Z');
return dateETC.toString();
}
#Override
public boolean handleMessage(SOAPMessageContext soapMessageContext) {
Boolean outboundProperty = (Boolean) soapMessageContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outboundProperty) {
try {
SOAPEnvelope soapEnvelope = soapMessageContext.getMessage().getSOAPPart().getEnvelope();
SOAPHeader header = soapEnvelope.getHeader();
if (header == null) {
header = soapEnvelope.addHeader();
}
SOAPElement securityHeaderElement = header.addChildElement("Security", "wsse", URL_WSSE_NAMESPACE);
securityHeaderElement.addAttribute(soapEnvelope.createName("S:mustUnderstand"), "1");
// Add Timestamp element to "Security" soapHeaderElement
// Sample: <u:Timestamp>
// <u:Created>2011-10-13T08:20:01.183Z</u:Created>
// <u:Expires>2011-10-13T17:25:01.183Z</u:Expires>
// </u:Timestamp>
javax.xml.soap.Name timestampElementName = soapEnvelope.createName("Timestamp", "wsu", URL_WSU_NAMESPACE);
SOAPElement timestampSOAPElement = securityHeaderElement.addChildElement(timestampElementName);
String created = getCurrentDateTime();
String expires = getCurrentDateTimePlusDelay(60L*60L); /* 60 minutes delay */
// Add Created to Timestamp
SOAPElement createdSOAPElement = timestampSOAPElement
.addChildElement("Created"/* local name */, "wsu" /* prefix */, URL_WSU_NAMESPACE);
createdSOAPElement.addTextNode(created);
// Add Expires to Timestamp
SOAPElement expiresSOAPElement = timestampSOAPElement
.addChildElement("Expires"/* local name */, "wsu" /* prefix */,URL_WSU_NAMESPACE);
expiresSOAPElement.addTextNode(expires);
// Add usernameToken to "Security" soapHeaderElement
javax.xml.soap.Name usernameTokenElementName = soapEnvelope.createName("UsernameToken", "wsse",
URL_WSSE_NAMESPACE);
SOAPElement usernameTokenSOAPElement = securityHeaderElement.addChildElement(usernameTokenElementName);
// Add Username to usernameToken
SOAPElement userNameSOAPElement = usernameTokenSOAPElement
.addChildElement("Username"/* local name */, "wsse" /* prefix */, URL_WSSE_NAMESPACE);
userNameSOAPElement.addTextNode(this.usernameText);
// Add password to UsernameToken
javax.xml.soap.Name passwordElementName = soapEnvelope.createName("Password", "wsse", URL_WSSE_NAMESPACE);
SOAPElement passwordSOAPElement = usernameTokenSOAPElement.addChildElement(passwordElementName);
/* Add "Type" attribute to <Password> header element */
//passwordSOAPElement.addAttribute(soapEnvelope.createName("Type", "", ""),
// "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
passwordSOAPElement.addTextNode(this.passwordText);
} catch (Exception e) {
throw new RuntimeException("Error on wsSecurityHandler: " + e.getMessage());
}
}
return true;
}
#Override
public void close(MessageContext context) {
// TODO Auto-generated method stub
}
#Override
public boolean handleFault(SOAPMessageContext context) {
// TODO Auto-generated method stub
return true;
}
#Override
public Set<QName> getHeaders() {
// throw new UnsupportedOperationException("Not supported yet.");
final QName securityHeader = new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
"Security", "wsse");
final HashSet headers = new HashSet();
headers.add(securityHeader);
return headers;
}
}
You can also use Apache wss4j to easily add the header and also encrypt you password.
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.message.WSSecHeader;
import org.apache.ws.security.message.WSSecUsernameToken;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import java.io.ByteArrayOutputStream;
import java.util.Set;
public class WSSecurityHeaderSOAPHandler implements SOAPHandler<SOAPMessageContext> {
private final String usernameText;
private final String passwordText;
public WSSecurityHeaderSOAPHandler(String usernameText, String passwordText) {
this.usernameText = usernameText;
this.passwordText = passwordText;
}
#Override
public boolean handleMessage(SOAPMessageContext context) {
Boolean outboundProperty = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outboundProperty.booleanValue()) {
try {
SOAPMessage soapMessage = context.getMessage();
soapMessage.removeAllAttachments();
SOAPPart soappart = soapMessage.getSOAPPart();
WSSecHeader wsSecHeader = new WSSecHeader();
wsSecHeader.insertSecurityHeader(soappart);
WSSecUsernameToken token = new WSSecUsernameToken();
token.setPasswordType(WSConstants.PASSWORD_DIGEST);
token.setUserInfo(usernameText, passwordText);
token.build(soappart, wsSecHeader);
soapMessage.saveChanges();
} catch (Exception e) {
throw new RuntimeException("Error on wsSecurityHandler: " + e.getMessage());
}
}
return true;
}
#Override
public boolean handleFault(SOAPMessageContext context) {
return false;
}
#Override
public void close(MessageContext context) {
}
#Override
public Set<QName> getHeaders() {
return null;
}
}
And you need to update your request like this:
// This is the block that apply the Ws Security to the request
BindingProvider bindingProvider = (BindingProvider) portType;
List<Handler> handlerChain = new ArrayList<>();
handlerChain.add(new WSSecurityHeaderSOAPHandler("username", "password"));
bindingProvider.getBinding().setHandlerChain(handlerChain);
Maven Dependency:
<dependency>
<groupId>org.apache.ws.security</groupId>
<artifactId>wss4j</artifactId>
<version>1.6.19</version>
</dependency>