Issues in Apache CXF for getting server stacktrace in Exception_Exception - java

I have implemented Apache CXF WebService and trying to access WebService through Swings Application.
The problem that I am facing is CXF has created a class named Exception_Exception in client side from the WSDL. When an exception occurs in server side, the client Exception_Exception gets invokes but I don't receive the same stack trace of server in Exception_Exception stack trace.
Below is the class generated by CXF:
package com.abc.it.vcare.service;
import javax.xml.ws.WebFault;
/**
* This class was generated by the JAX-WS RI.
* JAX-WS RI 2.2-hudson-752-
* Generated source version: 2.2
*
*/
#WebFault(name = "Exception", targetNamespace = "http://service.vcare.it.abc.com/")
public class Exception_Exception
extends java.lang.Exception
{
/**
* Java type that goes as soapenv:Fault detail element.
*
*/
private com.axiom.it.vcare.service.Exception faultInfo;
/**
*
* #param message
* #param faultInfo
*/
public Exception_Exception(String message, com.axiom.it.vcare.service.Exception faultInfo) {
super(message);
this.faultInfo = faultInfo;
}
/**
*
* #param message
* #param faultInfo
* #param cause
*/
public Exception_Exception(String message, com.axiom.it.vcare.service.Exception faultInfo, Throwable cause) {
super(message, cause);
this.faultInfo = faultInfo;
}
/**
*
* #return
* returns fault bean: com.axiom.it.vcare.service.Exception
*/
public com.axiom.it.vcare.service.Exception getFaultInfo() {
return faultInfo;
}
}
Please help, what should I do to get the same StackTrace given in Server Exception in my client side Exception_Exception.
Thanks,
Jai G.

What version of CXF are you using? This is an old CXF issue that has been addressed in the most recent versions. Try using version 2.7.0 of CXF, that should solve the problem.

Related

Apache Camel: Send Text Message with Twilio

I'm trying to send a text message over Apache Camel using the camel-twilio component. Since I never used the Twilio API (neither natively nor using Apache Camel), I'm not sure if I got the parameters right. Here's the method I wrote:
/**
* Sends a text message to the given recipient's number (parameter to)
*
* #param username:
* Twilio username (email)
* #param password:
* Twilio password (in plain text)
* #param accountSid:
* Twilio account sid (from the dashboard)
* #param from:
* registered phone number (starting with country prefix +XX)
* #param to:
* the recipient's phone number (starting with country prefix +XX)
* #param message:
* the message to be sent (plain text)
* #throws Exception
*/
public static void sendTextMessage(String username, String password, String accountSid, String from, String to,
String message) throws Exception {
String route = String.format("twilio:message/creator?username=%s&password=%s&accountSid=%s&from=%s&to=%s",
username, password, accountSid, from, to);
CamelContext context = new DefaultCamelContext();
context.addRoutes(new RouteBuilder() {
#Override
public void configure() throws Exception {
from("direct:message").to(route);
}
});
context.start();
ProducerTemplate producer = context.createProducerTemplate();
producer.sendBody("direct:message", message);
context.stop();
}
The most important line is the creation of the route, the first of the method. When I'm running this method with parameters according to the JavaDoc, I get this error:
Caused by: org.apache.camel.RuntimeCamelException: Missing properties for creator, need one or more from [pathAccountSid, mediaUrl, messagingServiceSid, body]
So I thought to add the parameter messagingServiceSid, providing my accountSid again:
String route = String.format("twilio:message/creator?username=%s&password=%s&accountSid=%s&from=%s&to=%s&messagingServiceSid=%s",
username, password, accountSid, from, to, accountSid);
Now I get this error message:
Caused by: java.lang.IllegalArgumentException: No matching method for message/creator, with arguments [messagingServiceSid, from, to]
What am I doing wrong?
EDIT: These are my Maven dependencies:
<dependencies>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>2.20.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-twilio</artifactId>
<version>2.20.1</version>
</dependency>
</dependencies>
EDIT 2: Here's the modified and working version of the method:
/**
* Sends a text message to the given recipient's number (parameter to)
*
* #param accountSid:
* Twilio account sid (from the dashboard)
* #param authToken:
* Twilio auth token (from the dashboard)
* #param from:
* registered phone number (starting with country prefix +XX)
* #param to:
* the recipient's phone number (starting with country prefix +XX)
* #param message:
* the message to be sent (plain text)
* #throws Exception
*/
public static void sendTextMessage(String accountSid, String authToken, String from, String to, String message)
throws Exception {
CamelContext context = new DefaultCamelContext();
TwilioComponent twilio = context.getComponent("twilio", TwilioComponent.class);
twilio.getConfiguration().setUsername(accountSid);
twilio.getConfiguration().setPassword(authToken);
context.addRoutes(new RouteBuilder() {
#Override
public void configure() throws Exception {
from("direct:message")
.setHeader("CamelTwilioTo", constant(new PhoneNumber(to)))
.setHeader("CamelTwilioFrom", constant(new PhoneNumber(from)))
.setHeader("CamelTwilioBody", constant(message))
.to("twilio://message/creator");
}
});
context.start();
ProducerTemplate producer = context.createProducerTemplate();
producer.sendBody("direct:message", message);
context.stop();
}
I have to say that to work efficiently with camel-twilio, you need to have a good understanding on Twilio Java API. In your case, let's get familiar with the MessageCreator API here:
https://www.twilio.com/docs/libraries/reference/twilio-java/7.17.0/com/twilio/rest/api/v2010/account/MessageCreator.html
With that said, first of all, since the username (i.e. accountSid) and password should be something shared in a camel-twilio component, let's set them at the component:
TwilioComponent twilio = context.getComponent("twilio", TwilioComponent.class);
twilio.getConfiguration().setUsername(username);
twilio.getConfiguration().setPassword(password);
(Note most of the time the twilio username and accoundSid refer to the same thing, so you can use only one of them.)
Once the username/password are set up, let's use the MessageCreator. The simplest constructor you can use would be MessageCreator(PhoneNumber to, PhoneNumber from, String body), but since to and from have to be PhoneNumber instances, it's easier to pass them to the endpoint as Camel message headers instead of embedding them to the endpoint URI as endpoint parameters. (NOTE: Any of the camel-twilio endpoint options can be provided in a message header with CamelTwilio prefix.)
This would look something like the following:
public void configure() throws Exception {
from("direct:message")
.setHeader("CamelTwilioTo", constant(new PhoneNumber(to)))
.setHeader("CamelTwilioFrom", constant(new PhoneNumber(from)))
.setHeader("CamelTwilioBody", constant(message))
.to("twilio://message/creator");
}
Note, at this moment, the endpoint URI can be as simple as twilio://message/creator.
Now you should be able to send texts to Twilio.
FYI, there is a working example of camel-twilio with Spring Boot:
https://github.com/tadayosi/demo-camel-hawtio-springboot

Error during EJB3 call

I have written a simple Ejb program, by looking from
http://mrbool.com/how-to-use-enterprise-java-beans-3-x-based-application-with-websphere-8-5-application-server/28063
The files are
package ejb3.test;
import javax.ejb.Remote;
/**
* TODO: Document me!
*
* #author aprashanth
*
*/
#Remote
public interface ITestEJBRemoteInterface {
public boolean checkNames(String fsName);
}
Implementation Class:
package ejb3.test;
/**
* TODO: Document me!
*
* #author aprashanth
*
*/
import java.util.Arrays;
import java.util.List;
import javax.ejb.Stateless;
/** * Session Bean implementation class TestEJB */
#Stateless
public class TestEJB implements ITestEJBRemoteInterface {
List<String> moListOfNames = Arrays.asList("Kevin","Jiten","Martina","Brian");
/** * Default constructor. */
public TestEJB() { }
/** * Find if the passed name is present in the default list of names * *
*
* #return */
public boolean checkNames(String fsName) {
boolean lboolNamePresent = false;
if(fsName != null)
{
lboolNamePresent = moListOfNames.contains(fsName);
}
return lboolNamePresent;
}
}
Ejb-jar.xml:
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd" version="3.1">
<display-name>TestEJB3 </display-name>
<ejb-client-jar>TestEJB3Client.jar</ejb-client-jar>
</ejb-jar>
At the client side:
I have created the stub using createStub.bat of IBM.and that jar is imported at the client side.
package ejb31.test;
/**
* TODO: Document me!
*
* #author aprashanth
*
*/
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import ejb3.test.ITestEJBRemoteInterface;
public class TestEJBClient {
/** * #param args */
public static void main(String[] args) {
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory");
props.put(javax.naming.Context.PROVIDER_URL, "iiop://localhost:2809");
ITestEJBRemoteInterface loEJB =null;
Object lobj; try { InitialContext ctx = new InitialContext(props);
lobj = ctx.lookup("checkName");
if (lobj instanceof ITestEJBRemoteInterface) {
loEJB = (ITestEJBRemoteInterface) lobj;
}
String lsName = "Imran";
System.out.println("Is "+ lsName + " present in the list:: "+loEJB.checkNames(lsName));
System.out.println("EJB run successful");
} catch (NamingException e) {
e.printStackTrace();
}
}
}
My project structure and the imported libraries as in the below figure:
At the WAS side, setup steps are as below:
Port
Installation Steps
Lastly JndI Configuration.
When I run the client code, I get the following error.
JSAS1480I: Security is not enabled because the ConfigURL property file is not set.
javax.naming.NamingException: Error getting WsnNameService properties [Root exception is org.omg.CORBA.TRANSIENT: initial and forwarded IOR inaccessible vmcid: 0x4942f000 minor code: 3591 completed: No]
at com.ibm.ws.naming.util.WsnInitCtxFactory.mergeWsnNSProperties(WsnInitCtxFactory.java:1552)
at com.ibm.ws.naming.util.WsnInitCtxFactory.getRootContextFromServer(WsnInitCtxFactory.java:1042)
at com.ibm.ws.naming.util.WsnInitCtxFactory.getRootJndiContext(WsnInitCtxFactory.java:962)
at com.ibm.ws.naming.util.WsnInitCtxFactory.getInitialContextInternal(WsnInitCtxFactory.java:614)
at com.ibm.ws.naming.util.WsnInitCtx.getContext(WsnInitCtx.java:128)
at com.ibm.ws.naming.util.WsnInitCtx.getContextIfNull(WsnInitCtx.java:765)
at com.ibm.ws.naming.util.WsnInitCtx.lookup(WsnInitCtx.java:164)
at com.ibm.ws.naming.util.WsnInitCtx.lookup(WsnInitCtx.java:179)
at javax.naming.InitialContext.lookup(InitialContext.java:411)
at ejb31.test.TestEJBClient.main(TestEJBClient.java:27)
Caused by: org.omg.CORBA.TRANSIENT: initial and forwarded IOR inaccessible vmcid: 0x4942f000 minor code: 3591 completed: No
at com.ibm.rmi.corba.ClientDelegate.createRequest(ClientDelegate.java:1276)
at com.ibm.CORBA.iiop.ClientDelegate.createRequest(ClientDelegate.java:1457)
at com.ibm.rmi.corba.ClientDelegate.createRequest(ClientDelegate.java:1164)
at com.ibm.CORBA.iiop.ClientDelegate.createRequest(ClientDelegate.java:1423)
at com.ibm.rmi.corba.ClientDelegate.request(ClientDelegate.java:1886)
at com.ibm.CORBA.iiop.ClientDelegate.request(ClientDelegate.java:1379)
at org.omg.CORBA.portable.ObjectImpl._request(ObjectImpl.java:449)
at com.ibm.WsnBootstrap._WsnNameServiceStub.getProperties(_WsnNameServiceStub.java:38)
at com.ibm.ws.naming.util.WsnInitCtxFactory.mergeWsnNSProperties(WsnInitCtxFactory.java:1549)
... 9 more
Caused by: java.net.ConnectException: connect: Address is invalid on local machine, or port is not valid on remote machine
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:83)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:579)
at com.ibm.ws.orbimpl.transport.WSTCPTransportConnection.createSocket(WSTCPTransportConnection.java:313)
at com.ibm.CORBA.transport.TransportConnectionBase.connect(TransportConnectionBase.java:357)
at com.ibm.ws.orbimpl.transport.WSTransport.getConnection(WSTransport.java:437)
at com.ibm.CORBA.transport.TransportBase.getConnection(TransportBase.java:187)
at com.ibm.rmi.iiop.TransportManager.get(TransportManager.java:97)
at com.ibm.rmi.iiop.GIOPImpl.getConnection(GIOPImpl.java:130)
at com.ibm.rmi.iiop.GIOPImpl.locate(GIOPImpl.java:219)
at com.ibm.rmi.corba.ClientDelegate.locate(ClientDelegate.java:1983)
at com.ibm.rmi.corba.ClientDelegate._createRequest(ClientDelegate.java:2008)
at com.ibm.rmi.corba.ClientDelegate.createRequest(ClientDelegate.java:1186)
at com.ibm.rmi.corba.ClientDelegate.createRequest(ClientDelegate.java:1272)
... 17 more
Note: Port and address is correct:
Screen Shot of Security
New error on changing the inbound Configuration
JSAS1480I: Security is not enabled because the ConfigURL property file is not set.
Exception in thread "P=818203:O=0:CT" java.lang.NullPointerException
at ejb31.test.TestEJBClient.main(TestEJBClient.java:32)
The war file which is deployed.
inside Client
Inside server.jar inside war file
Hmm, you have to look better on your screenshot, as it is clearly visible that Enable Administrative Security is CHECKED.
So you either have to disable SSL in the RMI/IIOP inbound transport configuration, or properly configure your client to use SSL.
Something like this:
<java_install_root>/bin/java
-classpath com.ibm.ws.ejb.thinclient_8.5.0.jar:<list_of_your_application_jars_and_classes>
-Djava.naming.provider.url=iiop://<your_application_server_machine_name>
-Dcom.ibm.SSL.ConfigURL=file:///home/user1/ssl.client.props
-Dcom.ibm.CORBA.ConfigURL=file:///home/user1/sas.client.props
<fully_qualified_class_name_to_run>
For details check the following page - Running the IBM Thin Client for Enterprise JavaBeans (EJB)
UPDATE
Now you have issue in the code. You have to use PortableRemoteObject.narrow for unmanaged clients.
Instead of:
Object lobj; try { InitialContext ctx = new InitialContext(props);
lobj = ctx.lookup("checkName");
if (lobj instanceof ITestEJBRemoteInterface) { // <##### this is the problem
loEJB = (ITestEJBRemoteInterface) lobj;
}
use:
lobj = initCtx.lookup(ejbJNDIName);
loEJB = (ITestEJBRemoteInterface) javax.rmi.PortableRemoteObject.narrow(lobj , ITestEJBRemoteInterface.class);
For details see How to lookup the Remote Interface of an EJB 3 without using Dependency Injection

Spring Stomp over Websocket: Stream large files

My SockJs client in webpage, sends message with a frame size of 16K. The message size limit is what determines the max size of the file that I can transfer.
Below is what I found in the doc.
/**
* Configure the maximum size for an incoming sub-protocol message.
* For example a STOMP message may be received as multiple WebSocket messages
* or multiple HTTP POST requests when SockJS fallback options are in use.
*
* <p>In theory a WebSocket message can be almost unlimited in size.
* In practice WebSocket servers impose limits on incoming message size.
* STOMP clients for example tend to split large messages around 16K
* boundaries. Therefore a server must be able to buffer partial content
* and decode when enough data is received. Use this property to configure
* the max size of the buffer to use.
*
* <p>The default value is 64K (i.e. 64 * 1024).
*
* <p><strong>NOTE</strong> that the current version 1.2 of the STOMP spec
* does not specifically discuss how to send STOMP messages over WebSocket.
* Version 2 of the spec will but in the mean time existing client libraries
* have already established a practice that servers must handle.
*/
public WebSocketTransportRegistration setMessageSizeLimit(int messageSizeLimit) {
this.messageSizeLimit = messageSizeLimit;
return this;
}
MY QUESTION:
Can I setup a partial messaging so that a file is transferred part by part and is not getting transferred as a single message as it is been done now?
Update:
Still looking for a solution with partial messaging
Meanwhile using HTTP now for large messages (which is file uploads/downloads in my application).
Can I setup a partial messaging so that a file is transferred part by part and is not getting transferred as a single message as it is been done now?
Yes. Here is the relevant Config from my Spring boot experimental project - basically UploadWSHandler is registered and WebSocketTransportRegistration.setMessageSizeLimit is set.
#Configuration
#EnableWebSocket
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer implements WebSocketConfigurer {
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new UploadWSHandler(), "/binary");
}
#Override
public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
registration.setMessageSizeLimit(50 * 1024 * 1024);
}
}
The UploadWShandler is as follows. Sorry too much code here - Key points
supportsPartialMessage which returns true.
handleBinaryMessage will be called multiple times with partial message so we need to assemble the bytes. So afterConnectionEstablished establishes an identity using the websocket URL query. But you don't have to use this mechanism. The reason why I choose this mechanism is to keep the client side simple so that I call webSocket.send(files[0]) only once i.e. I am not slicing the file blob object on the javascript side. (side point: I want to use plain websocket on client side - no stomp/socks)
The iternal client side chunking mechanism provides message.isLast() last message
For demo purposes I am writing this to file system and accumulating those bytes in memory with FileUploadInFlight but you don't have to do this and can stream somewhere else as you go.
public class UploadWSHandler extends BinaryWebSocketHandler {
Map<WebSocketSession, FileUploadInFlight> sessionToFileMap = new WeakHashMap<>();
#Override
public boolean supportsPartialMessages() {
return true;
}
#Override
protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception {
ByteBuffer payload = message.getPayload();
FileUploadInFlight inflightUpload = sessionToFileMap.get(session);
if (inflightUpload == null) {
throw new IllegalStateException("This is not expected");
}
inflightUpload.append(payload);
if (message.isLast()) {
Path basePath = Paths.get(".", "uploads", UUID.randomUUID().toString());
Files.createDirectories(basePath);
FileChannel channel = new FileOutputStream(
Paths.get(basePath.toString() ,inflightUpload.name).toFile(), false).getChannel();
channel.write(ByteBuffer.wrap(inflightUpload.bos.toByteArray()));
channel.close();
session.sendMessage(new TextMessage("UPLOAD "+inflightUpload.name));
session.close();
sessionToFileMap.remove(session);
}
String response = "Upload Chunk: size "+ payload.array().length;
System.out.println(response);
}
#Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
sessionToFileMap.put(session, new FileUploadInFlight(session));
}
static class FileUploadInFlight {
String name;
String uniqueUploadId;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
/**
* Fragile constructor - beware not prod ready
* #param session
*/
FileUploadInFlight(WebSocketSession session) {
String query = session.getUri().getQuery();
String uploadSessionIdBase64 = query.split("=")[1];
String uploadSessionId = new String(Base64Utils.decodeUrlSafe(uploadSessionIdBase64.getBytes()));
System.out.println(uploadSessionId);
List<String> sessionIdentifiers = Splitter.on("\\").splitToList(uploadSessionId);
String uniqueUploadId = session.getRemoteAddress().toString()+sessionIdentifiers.get(0);
String fileName = sessionIdentifiers.get(1);
this.name = fileName;
this.uniqueUploadId = uniqueUploadId;
}
public void append(ByteBuffer byteBuffer) throws IOException{
bos.write(byteBuffer.array());
}
}
}
BTW a working project is also sprint-boot-with-websocked-chunking-assembly-and-fetch in with-websocked-chunking-assembly-and-fetch branch

Java, Websockets, tyrus server: handshake error [duplicate]

I have written a client program that connects to my websocket on the server. I set up tomcat8 with the examples working and hit the EchoAnnotation endpoint with my client program.
I wrote this endpoint program as follows:
#ServerEndpoint(value = "/websocket")
public class PortServer implements AirMessageListener {
public PortServer() { }
#OnOpen
public void start(Session session) {
//do stuff
}
#OnClose
public void end() {
//do stuff
}
}
#OnMessage
public void incoming(String message) {
//do stuff
}
#OnError
public void onError(Throwable tw) throws Throwable {
//do stuff
}
I compile this and create a war file called portserver and drop it into my tomcat webapps directory. I then switched my client program from connecting to: ws://localhost:8080/examples/websocket/echoAnnotation to ws://localhost:8080/portserver/websocket and run it. I get:
Connecting to:ws://localhost:8080/portserver/websocket
Exception in thread "main" com.corrisoft.air.exception.AirException: Error connecting to server
at com.corrisoft.air.socket.AirSocketClient.<init>(AirSocketClient.java:60)
at test.corrisoft.air.portserver.SocketConversation.<init>(SocketConversation.java:46)
at test.corrisoft.air.portserver.RunPortServerTester.initConfigProperties(RunPortServerTester.java:76)
at test.corrisoft.air.portserver.RunPortServerTester.<init>(RunPortServerTester.java:34)
at test.corrisoft.air.portserver.RunPortServerTester.main(RunPortServerTester.java:109)
Caused by: javax.websocket.DeploymentException: Handshake error.
at org.glassfish.tyrus.client.ClientManager$1$1.run(ClientManager.java:466)
at org.glassfish.tyrus.client.ClientManager$1.run(ClientManager.java:502)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.glassfish.tyrus.client.ClientManager$SameThreadExecutorService.execute(ClientManager.java:654)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:359)
at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:195)
at com.corrisoft.air.socket.AirSocketClient.<init>(AirSocketClient.java:58)
... 4 more
Caused by: org.glassfish.tyrus.core.HandshakeException: Response code was not 101: 404.
at org.glassfish.tyrus.core.Handshake.validateServerResponse(Handshake.java:279)
at org.glassfish.tyrus.client.TyrusClientEngine.processResponse(TyrusClientEngine.java:138)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientFilter.handleHandshake(GrizzlyClientFilter.java:318)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientFilter.handleRead(GrizzlyClientFilter.java:288)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:291)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:209)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:137)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:115)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:550)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
at java.lang.Thread.run(Thread.java:744)
I placed an index.html inside my portserver app and can hit: http://localhost:8080/portserver just fine, which means the directories are OK. I then verified that my class was in my WEB-INF/classes directory.
I looked at the examples and found the ExamplesConfig class that I thought might be a "magic" class that enables the endpoints, so I implemented my own and and stuck in the jar file.
/**
*
*/
package com.corrisoft.air.portserver;
import java.util.HashSet;
import java.util.Set;
import javax.websocket.Endpoint;
import javax.websocket.server.ServerApplicationConfig;
import javax.websocket.server.ServerEndpointConfig;
/**
* #author Corrisoft Android Development
*/
public class WebSocketConfig implements ServerApplicationConfig {
/* (non-Javadoc)
* #see javax.websocket.server.ServerApplicationConfig#getAnnotatedEndpointClasses(java.util.Set)
*/
#Override
public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scanned) {
// Deploy all WebSocket endpoints defined by annotations in the
// web application. Filter out all others to avoid issues when running
// tests on Gump
Set<Class<?>> results = new HashSet<>();
for (Class<?> clazz : scanned) {
if (clazz.getPackage().getName().startsWith("com.corrisoft.air")) {
System.out.println("Adding endpoint for:" + clazz.getName());
results.add(clazz);
}
}
return results;
}
/* (non-Javadoc)
* #see javax.websocket.server.ServerApplicationConfig#getEndpointConfigs(java.util.Set)
*/
#Override
public Set<ServerEndpointConfig> getEndpointConfigs( Set<Class<? extends Endpoint>> scanned) {
return null;
}
}
It does not seem to be running this class.
Is there some configuration I missed?
Turns out that the problem was that one of my dependent classes was missing from the classpath. Tomcat 8, under these circumstances, doesn't add the endpoint and doesn't throw an exception into the log.
I deployed the same war file to tomcat 7 and got an exception. Worked the classpath until it was good and then deployed back to tomcat 8 where it is now working.
I created defect 56442 here: https://issues.apache.org/bugzilla/show_bug.cgi?id=56442 for tomcat eating the exception instead of displaying in the log.
For anyone else plagued by this; take a CLOSE look at your URI. I was piecing my url together, based on a configuration file. I missed a single "/" character when constructing the URL, and was convinced that it was correct! If you do stuff like the following, I suggest, printing out the "constructed URL" and studying that closely before chasing your tail:
public static final String WEBSOCKETHOST = "localhost"; // TODO: Get from configuration
public static final int WEBSOCKETPORT = 10080; // TODO: Get from configuration
public static final String WEBSOCKETSERVERROOT = "/sceagents"; // TODO: Get from configuration
public static final String WEBSOCKETSERVERENDPOINT = "neo"; // TODO: Get from configuration
public static final String WEBSOCKETPROTOCOL = "ws"; // TODO: Get from configuration
String uri = WEBSOCKETPROTOCOL + "://" + WEBSOCKETHOST + ":" + Integer.toString(WEBSOCKETPORT) + WEBSOCKETSERVERROOT + "/" + WEBSOCKETSERVERENDPOINT;

How to send an email using MS exchange server

I am trying to sent an email using my company's mail server. But I am getting the following exception
Caused by: com.sun.mail.smtp.SMTPSendFailedException: 530 5.7.1 Client was not authenticated
at com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:1388)
at com.sun.mail.smtp.SMTPTransport.mailFrom(SMTPTransport.java:959)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:583)
at javax.mail.Transport.send0(Transport.java:169)
at javax.mail.Transport.send(Transport.java:98)
Here is my sample code,
Properties props = System.getProperties();
// Setup mail server
props.put("mail.smtp.host", "example.server.com");
props.put("mail.smtp.auth", "true");
props.put("mail.debug", "true");
props.put("mail.smtp.port", "25");
// Get session
//Session session = Session.getDefaultInstance(props, null);
Session session = Session.getDefaultInstance(props,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("username", "password");
}
});
// Define message
MimeMessage message = new MimeMessage(session);
// Set the from address
message.setFrom(new InternetAddress(from));
// Set the to address
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
// Set the subject
message.setSubject("Hello JavaMail");
// Set the content
message.setText("Welcome to JavaMail");
// Send message
Transport.send(message);
What piece of code is wrong?
As as username and password , I am using my company's email address and password.
The 5.7.1 is probably caused by exchange and not your code. You may just need to enable relaying on the server. Either for anonymous users or from a certain IP address. I'm not an expert on Exchange but I have got this working before. Here is the last solution I tested that works:
If a 5.7.1 error is encountered when trying to send an email via SMTP on an exchange server when the user has been authenticated..
For ref the issue you just had was caused by a setting on the Exchange 2007 server – this would not normally be a problem on 2003 server
Fixed by doing below...
You can set this authentication setting via the GUI
In Server configuration / Hub Transport / Default <ServerName>
Right click, properties, Permission Groups
Check "Anonymous users" and then click OK
Obviously anon users is not too secure but you could see if this solves the problem.
When I will use a MS Exhange SMTP Server to send an email, I use the above maven dependency.
<dependency>
<groupId>com.microsoft.ews-java-api</groupId>
<artifactId>ews-java-api</artifactId>
<version>2.0</version>
</dependency>
For that reason I created a class that represents an email client for MS Exchange Servers. I use log4j for logging.
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
Below the MS Exchange client class (I use the builder pattern for the construction of the object for thread safety),
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import microsoft.exchange.webservices.data.core.ExchangeService;
import microsoft.exchange.webservices.data.core.enumeration.misc.ExchangeVersion;
import microsoft.exchange.webservices.data.core.exception.service.local.ServiceLocalException;
import microsoft.exchange.webservices.data.core.service.item.EmailMessage;
import microsoft.exchange.webservices.data.credential.ExchangeCredentials;
import microsoft.exchange.webservices.data.credential.WebCredentials;
import microsoft.exchange.webservices.data.property.complex.MessageBody;
import org.apache.log4j.Logger;
/**
* A client to connect to a MS Exchange SMTP Server.
*/
public final class ExchangeClient {
private static final Logger LOGGER = Logger.getLogger(ExchangeClient.class);
private final String hostname;
private final ExchangeVersion exchangeVersion;
private final String domain;
private final String username;
private final String password;
private final String subject;
private final String recipientTo;
private final List<String> recipientCc;
private final List<String> recipientBcc;
private final List<String> attachments;
private final String message;
private ExchangeClient(ExchangeClientBuilder builder) {
this.hostname = builder.hostname;
this.exchangeVersion = builder.exchangeVersion;
this.domain = builder.domain;
this.username = builder.username;
this.password = builder.password;
this.subject = builder.subject;
this.recipientTo = builder.recipientTo;
this.recipientCc = builder.recipientCc;
this.recipientBcc = builder.recipientBcc;
this.attachments = builder.attachments;
this.message = builder.message;
}
public static class ExchangeClientBuilder {
private String hostname;
private ExchangeVersion exchangeVersion;
private String domain;
private String username;
private String password;
private String subject;
private String recipientTo;
private List<String> recipientCc;
private List<String> recipientBcc;
private List<String> attachments;
private String message;
public ExchangeClientBuilder() {
this.exchangeVersion = ExchangeVersion.Exchange2010_SP1;
this.hostname = "";
this.username = "";
this.password = "";
this.subject = "";
this.recipientTo = "";
this.recipientCc = new ArrayList<>(0);
this.recipientBcc = new ArrayList<>(0);
this.attachments = new ArrayList<>(0);
this.message = "";
}
/**
* The hostname of the Exchange Web Service. It will be used for
* connecting with URI https://hostname/ews/exchange.asmx
*
* #param hostname the hostname of the MS Exchange Smtp Server.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder hostname(String hostname) {
this.hostname = hostname;
return this;
}
/**
* The Exchange Web Server version.
*
* #param exchangeVersion the Exchange Web Server version.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder exchangeVersion(ExchangeVersion exchangeVersion) {
this.exchangeVersion = exchangeVersion;
return this;
}
/**
* The domain of the MS Exchange Smtp Server.
*
* #param domain the domain of the Active Directory. The first part of
* the username. For example: MYDOMAIN\\username, set the MYDOMAIN.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder domain(String domain) {
this.domain = domain;
return this;
}
/**
* The username of the MS Exchange Smtp Server. The second part of the
* username. For example: MYDOMAIN\\username, set the username.
*
* #param username the username of the MS Exchange Smtp Server.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder username(String username) {
this.username = username;
return this;
}
/**
* The password of the MS Exchange Smtp Server.
*
* #param password the password of the MS Exchange Smtp Server.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder password(String password) {
this.password = password;
return this;
}
/**
* The subject for this send.
*
* #param subject the subject for this send.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder subject(String subject) {
this.subject = subject;
return this;
}
/**
* The recipient for this send.
*
* #param recipientTo the recipient for this send.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder recipientTo(String recipientTo) {
this.recipientTo = recipientTo;
return this;
}
/**
* You can specify one or more email address that will be used as cc
* recipients.
*
* #param recipientCc the first cc email address.
* #param recipientsCc the other cc email address for this send.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder recipientCc(String recipientCc, String... recipientsCc) {
// Prepare the list.
List<String> recipients = new ArrayList<>(1 + recipientsCc.length);
recipients.add(recipientCc);
recipients.addAll(Arrays.asList(recipientsCc));
// Set the list.
this.recipientCc = recipients;
return this;
}
/**
* You can specify a list with email addresses that will be used as cc
* for this email send.
*
* #param recipientCc the list with email addresses that will be used as
* cc for this email send.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder recipientCc(List<String> recipientCc) {
this.recipientCc = recipientCc;
return this;
}
/**
* You can specify one or more email address that will be used as bcc
* recipients.
*
* #param recipientBcc the first bcc email address.
* #param recipientsBcc the other bcc email address for this send.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder recipientBcc(String recipientBcc, String... recipientsBcc) {
// Prepare the list.
List<String> recipients = new ArrayList<>(1 + recipientsBcc.length);
recipients.add(recipientBcc);
recipients.addAll(Arrays.asList(recipientsBcc));
// Set the list.
this.recipientBcc = recipients;
return this;
}
/**
* You can specify a list with email addresses that will be used as bcc
* for this email send.
*
* #param recipientBcc the list with email addresses that will be used
* as bcc for this email send.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder recipientBcc(List<String> recipientBcc) {
this.recipientBcc = recipientBcc;
return this;
}
/**
* You can specify one or more email address that will be used as cc
* recipients.
*
* #param attachment the first attachment.
* #param attachments the other attachments for this send.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder attachments(String attachment, String... attachments) {
// Prepare the list.
List<String> attachmentsToUse = new ArrayList<>(1 + attachments.length);
attachmentsToUse.add(attachment);
attachmentsToUse.addAll(Arrays.asList(attachments));
// Set the list.
this.attachments = attachmentsToUse;
return this;
}
/**
* You can specify a list with email attachments that will be used for
* this email send.
*
* #param attachments the list with email attachments that will be used
* for this email send.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder attachments(List<String> attachments) {
this.attachments = attachments;
return this;
}
/**
* The body of the email message.
*
* #param message the body of the email message.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder message(String message) {
this.message = message;
return this;
}
/**
* Build a mail.
*
* #return an EmailApacheUtils object.
*/
public ExchangeClient build() {
return new ExchangeClient(this);
}
}
public boolean sendExchange() {
// The Exchange Server Version.
ExchangeService exchangeService = new ExchangeService(exchangeVersion);
// Credentials to sign in the MS Exchange Server.
ExchangeCredentials exchangeCredentials = new WebCredentials(username, password, domain);
exchangeService.setCredentials(exchangeCredentials);
// URL of exchange web service for the mailbox.
try {
exchangeService.setUrl(new URI("https://" + hostname + "/ews/Exchange.asmx"));
} catch (URISyntaxException ex) {
LOGGER.error("An exception occured while creating the uri for exchange service.", ex);
return false;
}
// The email.
EmailMessage emailMessage;
try {
emailMessage = new EmailMessage(exchangeService);
emailMessage.setSubject(subject);
emailMessage.setBody(MessageBody.getMessageBodyFromText(message));
} catch (Exception ex) {
LOGGER.error("An exception occured while setting the email message.", ex);
return false;
}
// TO recipient.
try {
emailMessage.getToRecipients().add(recipientTo);
} catch (ServiceLocalException ex) {
LOGGER.error("An exception occured while sstting the TO recipient(" + recipientTo + ").", ex);
return false;
}
// CC recipient.
for (String recipient : recipientCc) {
try {
emailMessage.getCcRecipients().add(recipient);
} catch (ServiceLocalException ex) {
LOGGER.error("An exception occured while sstting the CC recipient(" + recipient + ").", ex);
return false;
}
}
// BCC recipient
for (String recipient : recipientBcc) {
try {
emailMessage.getBccRecipients().add(recipient);
} catch (ServiceLocalException ex) {
LOGGER.error("An exception occured while sstting the BCC recipient(" + recipient + ").", ex);
return false;
}
}
// Attachements.
for (String attachmentPath : attachments) {
try {
emailMessage.getAttachments().addFileAttachment(attachmentPath);
} catch (ServiceLocalException ex) {
LOGGER.error("An exception occured while setting the attachment.", ex);
return false;
}
}
try {
emailMessage.send();
LOGGER.debug("An email is send.");
} catch (Exception ex) {
LOGGER.error("An exception occured while sending an email.", ex);
return false;
}
return true;
}
}
A working example,
// import microsoft.exchange.webservices.data.core.enumeration.misc.ExchangeVersion;
ExchangeClient client = new ExchangeClient.ExchangeClientBuilder()
.hostname("webmail.domainOfWeb.com")
.exchangeVersion(ExchangeVersion.Exchange2010)
.domain("ActiveDirectoryDomain")
.username("ActiveDirectoryUsername")
.password("ActiveDirectoryPassword")
.recipientTo("recipient#whatever.com")
.recipientCc("recipient#whatever.com") // Ignore it in case you will not use Cc recipients.
.recipientBcc("recipient#whatever.com") // Ignore it in case you will not use Bcc recipients.
.attachments("/home/username/image.png") // Ignore it in case you will not use attachements.
.subject("Test Subject")
.message("Test Message")
.build();
client.sendExchange();
Mail.jar (Version 1.4.0) has a compatibility issue with MS Exchange Server and throws 530 5.7.1 Client was not authenticated, even when Username and password are configured.
Upgrading the mail API to 1.4.4 OR 1.4.7 should resolve the issue.
Mail API's 1.4.7 can be download from the following URL: http://www.oracle.com/technetwork/java/javamail/index.html
In some companies, the Exchange server SMTP support is disable and you cannot ask them to enable it. In these cases, a reasonable solution is this one:
http://davmail.sourceforge.net/
Simple Java Mail worked for me. The only thing you have to check is for correct hostname, username, port and password TransportStrategy.SMTP_TLS:
new Mailer(host, port, username, password, TransportStrategy.SMTP_TLS).sendMail(email);
I had to use javamail + exchange. The messages returned were helpless.
Thanks to the stack, I got some hints.
Add this to your code
props.put("mail.smtp.starttls.enable","true");
Think of adding the certificates of the machines used too.
To find them, just go to your browser, export them and import to the cacerts file in use.
Please use the following code parts instead of Transport.send(message);
MimeMessage message = new MimeMessage(session);
message.saveChanges();
Transport transport = session.getTransport("smtp");
transport.connect(host, "user", "pwd");
transport.sendMessage(message, message.getAllRecipients());
transport.close();
I have tested in the local and it is working
The ews-java-api package is at end of life.
From https://github.com/OfficeDev/ews-java-api
Starting July 19th 2018, Exchange Web Services (EWS) will no longer receive feature updates. While the service will continue to receive security updates and certain non-security updates, product design and features will remain unchanged. This change also applies to the EWS SDKs for Java and .NET. More information here: https://developer.microsoft.com/en-us/graph/blogs/upcoming-changes-to-exchange-web-services-ews-api-for-office-365/

Categories