BaseX parrallel Client - basex

I have client like this :
import org.basex.api.client.ClientSession;
#Slf4j
#Component(value = "baseXAircrewClient")
#DependsOn(value = "baseXAircrewServer")
public class BaseXAircrewClient {
#Value("${basex.server.host}")
private String basexServerHost;
#Value("${basex.server.port}")
private int basexServerPort;
#Value("${basex.admin.password}")
private String basexAdminPassword;
#Getter
private ClientSession session;
#PostConstruct
private void createClient() throws IOException {
log.info("##### Creating BaseX client session {}", basexServerPort);
this.session = new ClientSession(basexServerHost, basexServerPort, UserText.ADMIN, basexAdminPassword);
}
}
It is a singleton injected in a service which run mulitple queries like this :
Query query = client.getSession().query(finalQuery);
return query.execute();
All threads query and share the same session.
With a single thread all is fine but with multiple thread I get some random (and weird) error, like the result of a query to as a result of another.
I feel that I should put a synchronized(){} arround query.execute() or open and close session for each query, or create a pool of session.
But I don't find any documentation how the use the session in parrallel.
Is this implementation fine for multithreading (and my issue is comming from something else) or should I do it differently ?

I ended creating a simple pool by adding removing the client from a ArrayBlockingQueue and it is working nicely :
#PostConstruct
private void createClient() throws IOException {
log.info("##### Creating BaseX client session {}", basexServerPort);
final int poolSize = 5;
this.resources = new ArrayBlockingQueue < ClientSession > (poolSize) {
{
for (int i = 0; i < poolSize; i++) {
add(initClient());
}
}
};
}
private ClientSession initClient() throws IOException {
ClientSession clientSession = new ClientSession(basexServerHost, basexServerPort, UserText.ADMIN, basexAdminPassword);
return clientSession;
}
public Query query(String finalQuery) throws IOException {
ClientSession clientSession = null;
try {
clientSession = resources.take();
Query result = clientSession.query(finalQuery);
return result;
} catch (InterruptedException e) {
log.error("Error during query execution: " + e.getMessage(), e);
} finally {
if (clientSession != null) {
try {
resources.put(clientSession);
} catch (InterruptedException e) {
log.error("Error adding to pool : " + e.getMessage(), e);
}
}
}
return null;
}

Related

javaFX : How to periodically load information from db and show it on a Label?

I want to execute a method periodically, this method get informations from database it show it into a label, I tried the following code :
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//update information
miseAjour();
}
}, 0, 2000);
when i run the main program, the background service run also normaly but when the informations changes on db i get this exception:
Exception in thread "Timer-0" java.lang.IllegalStateException: Not on FX application thread; currentThread = Timer-0
And this is the code of method miseAjour :
public void miseAjour(){
try {
dbConnection db = new dbConnection();
Connection connect = db.connectiondb();
connect.setAutoCommit(false);
Statement stmt= connect.createStatement();
ResultSet rs = stmt.executeQuery("SELECT count(*) as nbrAderent FROM gss_aderent ");
int nbrAderent = rs.getInt("nbrAderent");
rs.close();
stmt.close();
connect.commit();
connect.close();
main_nbrAdrTot.setText(nbrAderent + "");
} catch (SQLException ex) {
Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
}
}
You can Timer for this, but I would recommend to use the JavaFX provided API called as ScheduledService.
ScheduledService is made to execute the same Task at regular intervals and since it creates a Task internally, there are API which help you to bind the value to the UI controls.
ScheduledService<Object> service = new ScheduledService<Object>() {
protected Task<Object> createTask() {
return new Task<Object>() {
protected Object call() {
// Call the method and update the message
updateMessage(miseAjour());
return object; // Useful in case you want to return data, else null
}
};
}
};
service.setPeriod(Duration.seconds(10)); //Runs every 10 seconds
//bind the service message properties to your Label
label.textProperty().bind(service.messageProperty()); // or use your label -> main_nbrAdrTot
Inside the dbcall method miseAjour, return the value that you have fetched and you want to update the label with :
public String miseAjour(){
String nbrAderent = null;
try {
dbConnection db = new dbConnection();
Connection connect = db.connectiondb();
connect.setAutoCommit(false);
Statement stmt= connect.createStatement();
ResultSet rs = stmt.executeQuery("SELECT count(*) as nbrAderent FROM gss_aderent ");
nbrAderent = String.valueOf(rs.getInt("nbrAderent"));
connect.commit();
} catch (SQLException ex) {
Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
}
finally {
rs.close();
stmt.close();
connect.close();
}
return nbrAderent;
}
Finnaly i resolved the problem ,here is the code :
public class TimerServiceApp {
public void start() throws Exception {
TimerService service = new TimerService();
service.setPeriod(Duration.seconds(10));
service.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent t) {
main_nbrAdrTot.setText(t.getSource().getMessage());
}
});
service.start();
}
private class TimerService extends ScheduledService<Integer> {
private final StringProperty nbrTotAderent = new SimpleStringProperty();
public final void setTotalAderentNumber(String value ) {
nbrTotAderent.set(value);
}
public String getTotalAderentNumber() throws SQLException {
String nbrAderent = null;
ResultSet rs=null;
Statement stmt=null;
Connection connect=null;
try {
dbConnection db = new dbConnection();
connect = db.connectiondb();
connect.setAutoCommit(false);
stmt= connect.createStatement();
rs = stmt.executeQuery("SELECT count(*) as nbrAderent FROM gss_aderent ");
nbrAderent = String.valueOf(rs.getInt("nbrAderent"));
connect.commit();
} catch (SQLException ex) {
Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
}
finally {
rs.close();
stmt.close();
connect.close();
}
System.out.println(" Total aderent number updated to :" + nbrAderent + " Aderents ");
return nbrAderent;
}
protected Task<Integer> createTask() {
return new Task<Integer>() {
protected Integer call() throws SQLException {
nbrTotAderent.setValue(getTotalAderentNumber());
updateMessage(getTotalAderentNumber());
return Integer.parseInt(getTotalAderentNumber());
}
};
}
}
} `
and i called this service by :
TimerServiceApp s = new TimerServiceApp();
s.start();
i dont know if the solution is optimised but it work :) thank you #ItachiUchiha i took the solution from yout answer in the following link

Entity Framework Slow Closing Connection

I am builing an MVC 5 web app and I am using entity framework 6 and I have MS SQL Server 2008 R2 as my database. I use connection pooling to ensure that I get a connection as fast as possible for db operations. My connection string in my Web.config is as follows
<add name="MyConnectionPoolConnectionString" connectionString="Data Source=MyHOST;Initial Catalog=TEST_DB;User Id=sa;Password=password1; Min Pool Size=10;MultipleActiveResultSets=True;" providerName="System.Data.SqlClient" />
I notice that obtaining a connection from the connection pool is very fast i.e. some tens to hundreds of milliseconds
However, what I have also noticed is that closing the connection (which in a connection pool means the connection is returned to the pool) takes a rather long time (i.e. on the average between 2000ms and 5000ms (2 - 5 secs)).
Here is an excerpt from my profiling log
Time taken to open connection
2015-02-18 21:06:55,497 Opened connection at 18/02/2015 21:06:55 92.65 ms
Time taken to close / return connection
Closed connection at 18/02/2015 21:07:01 2543.06 ms
Notice that opening the connection takes 92ms and closing the connection takes 2500ms.
BTW, these stats are provided my the EF framework itself i.e. by setting the Log property of the Database prop on the EF context i.e.
MyTestAppDbContext.Database.Log = Logger.Debug;
What I dont understand is why it is so fast to get a connection from the connection pool but it takes so long for EF to return the connection back to the pool (i.e. close the connection) and more importantly how to speed up the release/closing of the connection
This is quite important for me because the web app needs to be quite responsive and as I have to create the EF Dbcontext for every request, if EF adds an extra 2 - 5 secs overhead to just close / release a connection, it reduces the responsiveness of the app.
MyTestAppDbContext.cs
public partial class MyTestAppDbContext : DbContext
{
public ILogger Logger { get; set; }
static MyTestAppDbContext()
{
System.Data.Entity.Database.SetInitializer<MyTestAppDbContext>(null);
}
public MyTestAppDbContext(ILogger logger)
: base("Name=MyConnectionPoolConnectionString")
{
this.Configuration.LazyLoadingEnabled = false;
this.Configuration.ProxyCreationEnabled = false;
Logger = logger;
this.Database.Log = Logger.Debug;
}
public override int SaveChanges()
{
Exception entityFrameworkExceptions = null;
String exMsg = "";
int result = 0;
try
{
if (this.ChangeTracker.HasChanges())
{
// Get all Added/Deleted/Modified entities (not Unmodified or Detached)
foreach (var ent in this.ChangeTracker.Entries().Where(p => p.State == EntityState.Added || p.State == EntityState.Deleted || p.State == EntityState.Modified))
{
// For each changed record, log the activity performed
Logger.Debug("Detected Changes");
}
result = base.SaveChanges();
}
}
catch (DbEntityValidationException dbEx)
{
entityFrameworkExceptions = dbEx;
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
//System.Diagnostics.Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
exMsg += String.Format("\nProperty: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
Logger.Debug(String.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage));
}
}
}
catch (DbUpdateException dbEx)
{
entityFrameworkExceptions = dbEx;
Logger.Debug(String.Format("Exception Message: {0}", dbEx.Message));
Logger.Debug(String.Format("InnerException: {0}", dbEx.InnerException));
Logger.Debug(String.Format("StackTrace: {0}", dbEx.StackTrace));
Logger.Debug(String.Format("Call Stack: {0}", CommonUtils.GetCallStackAsString()));
}
catch (Exception ex)
{
entityFrameworkExceptions = ex;
Logger.Debug(String.Format("Exception Message: {0}", ex.Message));
Logger.Debug(String.Format("InnerException: {0}", ex.InnerException));
Logger.Debug(String.Format("StackTrace: {0}", ex.StackTrace));
Logger.Debug(String.Format("Call Stack: {0}", CommonUtils.GetCallStackAsString()));
}
if (entityFrameworkExceptions != null)
{
exMsg = exMsg + "\n" + entityFrameworkExceptions.Message + #"\n" + entityFrameworkExceptions.StackTrace + #"\n" + entityFrameworkExceptions.InnerException;
entityFrameworkExceptions = new HttpException(500, #"Exception applying changes in PaceDBContext (i.e. Entity Framework)\n" + exMsg+"\n"+CommonUtils.GetCallStackAsString());
throw entityFrameworkExceptions;
}
return result;
}
}
IUnitOfWork.cs
public interface IUnitOfWork /*: IDisposable*/
{
MyTestAppDbContext MyTestAppDbContext { get; set; }
Exception Save();
}
UnitOfWork.cs
public class UnitOfWork : IUnitOfWork, IDisposable
{
private bool disposed = false;
public MyTestAppDbContext MyTestAppDbContext {get; set;}
public ILogger Logger { get; set; }
public Exception Save()
{
Exception entityFrameworkExceptions = null;
String exMsg = "";//, callStackAsString = "";
try
{
System.Diagnostics.Trace.TraceInformation("Saving Db Changes in UnitOfWork");
MyTestAppDbContext.SaveChanges();
System.Diagnostics.Trace.TraceInformation("Finished saving Db Changes in UnitOfWork");
}
catch (DbEntityValidationException dbEx)
{
entityFrameworkExceptions = dbEx;
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
exMsg += String.Format("\nProperty: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
Logger.Debug(String.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage));
}
}
}
catch (DbUpdateException dbEx)
{
entityFrameworkExceptions = dbEx;
this.LogException(dbEx);
}
catch (Exception ex)
{
entityFrameworkExceptions = ex;
this.LogException(ex);
}
if (entityFrameworkExceptions != null)
{
exMsg = "\n" + entityFrameworkExceptions.Message + #"\n" + entityFrameworkExceptions.StackTrace + #"\n" + entityFrameworkExceptions.InnerException+"\n"+CommonUtils.GetCallStackAsString();
entityFrameworkExceptions = new HttpException(500, #"Exception applying changes in PaceDBContext (i.e. Entity Framework)\n" + exMsg);
throw entityFrameworkExceptions;
}
return entityFrameworkExceptions;
}
protected virtual void Dispose(bool disposing)
{
this.Save();
if (!this.disposed)
{
if (disposing)
{
MyTestAppDbContext.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void LogException(Exception ex){
Logger.Debug(String.Format("Exception Message: {0}", ex.Message));
Logger.Debug(String.Format("InnerException: {0}", ex.InnerException));
Logger.Debug(String.Format("StackTrace: {0}", ex.StackTrace));
}
}
UserRepository.cs
public class UserRepository : IUserRepository
{
public IUnitOfWork UnitOfWork { get; private set; }
public UserRepository(IUnitOfWork unitOfWork)
{
this.UnitOfWork = unitOfWork;
}
public Users GetUserByUserId(string userId)
{
if (!String.IsNullOrEmpty(userId)){
var user = from u in UnitOfWork.MyTestAppDbContext.Users
where u.UserId.Trim().Equals(userId.Trim())
select u;
return user.SingleOrDefault();
}
return null;
}
public string GetUserFullName(string userId)
{
string fullname = null;
if (!String.IsNullOrEmpty(userId))
{
var user = (from u in UnitOfWork.MyTestAppDbContext.Users
where u.UserId.Trim().Equals(userId.Trim())
select u).SingleOrDefault();
if (user != null)
{
if (!String.IsNullOrEmpty(user.FirstName))
fullname += user.FirstName + " ";
if (!String.IsNullOrEmpty(user.LastName))
fullname += user.LastName;
}
}
return fullname;
}
public long GetUserGroupId(string userId)
{
if (!String.IsNullOrEmpty(userId))
{
var user = (from u in UnitOfWork.MyTestAppDbContext.Users
where u.UserId.Trim().Equals(userId.Trim())
select u).SingleOrDefault();
if (user != null)
return user.UserGroupId;
}
return -1;
}
}
Thanks

Using H2 database server how to notify changes to clients (JMS messaging)

I am successfully using H2 database in AUTO_SERVER mode so that a database file is shared among a number of desktop clients on a network transparently.
This way a server is elected among the clients and all other clients read from the tcp server.
What I'm missing is how a client or the server can notify all other desktop clients something has been changed in the database.
Right now I'm using a JGroups channel to let all clients comunicate one with each other however this is another point of failure and another leader election algorithm which runs in parallel with H2.
Isn't there any other method?
I have read about the JMS (Java Message Service Java API) which is supported in some databases. Any hint for H2?
Thanks
EDIT:
The following code is an adaptation of the current answer, if I start the Sender first (set args as "sender") he connects as server to the H2 database, then I execute Receiver (set args as "receiver") in remote machines and they connect as clients.
Yet only the server receives notifications, clients don't receive anything.
This makes sense from what I currently know: a trigger is only called on the server, a user defined function called from a client or server is called on the client or server but not across all clients (and server) connected to the database.
So is there a way to adapt the below to notify all connected instances of a change in the database?
import java.io.File;
import java.sql.*;
import java.util.concurrent.atomic.AtomicLong;
import org.h2.tools.TriggerAdapter;
public class TestSimpleDB2
{
public static void main(String[] args) throws Exception
{
//final String url = "jdbc:h2:mem:test;multi_threaded=true";
final String url = "jdbc:h2:" + File.separator + "mnt/testdir/PlanIGS" + File.separator
+ "persondb;create=true;AUTO_SERVER=TRUE;multi_threaded=true";
Connection conn = DriverManager.getConnection(url);
Statement stat = conn.createStatement();
boolean isSender = false;
args = new String[]
{
"sender"
};
for (String arg : args)
{
if (arg.contains("receiver"))
{
System.out.println("receiver starting");
isSender = false;
}
else if (arg.contains("sender"))
{
System.out.println("sender starting");
isSender = true;
}
}
if (isSender)
{
stat.execute("create alias wait_for_change for \""
+ TestSimpleDB2.class.getName()
+ ".waitForChange\"");
stat.execute("create table test(id identity)");
stat.execute("create trigger notifier "
+ "before insert, update, delete, rollback "
+ "on test call \""
+ TestSimpleDB2.Notifier.class.getName() + "\"");
Thread.sleep(1000);
for (int i = 0; i < 10; i++)
{
System.out.println("Sender: I change something...");
stat.execute("insert into test values(null)");
Thread.sleep(2000);
}
}
else
{
new Thread()
{
public void run()
{
try
{
Connection conn = DriverManager.getConnection(url);
for (int i = 0; i < 10; i++)
{
conn.createStatement().execute(
"call wait_for_change(100000)");
System.out.println("Receiver: event received");
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}.start();
}
conn.close();
}
static AtomicLong modCount = new AtomicLong();
public static void waitForChange(long maxWaitMillis)
{
synchronized (modCount)
{
try
{
modCount.wait(maxWaitMillis);
}
catch (InterruptedException e)
{
// ignore
}
}
}
public static class Notifier extends TriggerAdapter
{
public void fire(Connection conn, ResultSet oldRow, ResultSet newRow)
throws SQLException
{
modCount.incrementAndGet();
synchronized (modCount)
{
modCount.notifyAll();
}
}
}
}
H2 does not implement JMS (in fact I don't know of a database that does). However, you could build a simple notify mechanism within H2, using a trigger and a user defined function, as follows. Please note this would require the multi-threaded mode in H2, which is not fully tested yet. Because of that, it might make sense to use a separate database for messaging than the database you use for your data.
import java.sql.*;
import java.util.concurrent.atomic.AtomicLong;
import org.h2.tools.TriggerAdapter;
public class TestSimpleDb {
public static void main(String[] args) throws Exception {
final String url = "jdbc:h2:mem:test;multi_threaded=true";
Connection conn = DriverManager.getConnection(url);
Statement stat = conn.createStatement();
stat.execute("create alias wait_for_change for \"" +
TestSimpleDb.class.getName() +
".waitForChange\"");
stat.execute("create table test(id identity)");
stat.execute("create trigger notifier " +
"before insert, update, delete, rollback " +
"on test call \"" +
TestSimpleDb.Notifier.class.getName() + "\"");
new Thread() {
public void run() {
try {
Connection conn = DriverManager.getConnection(url);
for (int i = 0; i < 10; i++) {
conn.createStatement().execute(
"call wait_for_change(10000)");
System.out.println("Receiver: event received");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
Thread.sleep(500);
for (int i = 0; i < 10; i++) {
System.out.println("Sender: I change something...");
stat.execute("insert into test values(null)");
Thread.sleep(1000);
}
conn.close();
}
static AtomicLong modCount = new AtomicLong();
public static void waitForChange(long maxWaitMillis) {
synchronized (modCount) {
try {
modCount.wait(maxWaitMillis);
} catch (InterruptedException e) {
// ignore
}
}
}
public static class Notifier extends TriggerAdapter {
public void fire(Connection conn, ResultSet oldRow, ResultSet newRow)
throws SQLException {
modCount.incrementAndGet();
synchronized (modCount) {
modCount.notifyAll();
}
}
}
}

Send JSon from Server to Client in GCM

I am Using GCM (Google Cloud Messaging).In that what i want i want to send J Son from the server side .On Client side I want to receive that for simple message i have done but i am stucked how could i pass J Son from the server side to the client side.
Please help me to resolve this.
This is my Server side code
public class GCMBroadcast extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final String SENDER_ID = "";
private static final String ANDROID_DEVICE = "";
private List<String> androidTargets = new ArrayList<String>();
public GCMBroadcast() {
super();
androidTargets.add(ANDROID_DEVICE);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String collapseKey = "";
String userMessage = "";
try {
userMessage = request.getParameter("Message");
collapseKey = request.getParameter("CollapseKey");
} catch (Exception e) {
e.printStackTrace();
return;
}
Sender sender = new Sender(SENDER_ID);
Message message = new Message.Builder()
.collapseKey(collapseKey)
.addData("message", userMessage)
.build();
try {
MulticastResult result = sender.send(message, androidTargets, 1);
System.out.println("Response: " + result.getResults().toString());
if (result.getResults() != null) {
int canonicalRegId = result.getCanonicalIds();
if (canonicalRegId != 0) {
System.out.println("response " +canonicalRegId );
}
} else {
int error = result.getFailure();
System.out.println("Broadcast failure: " + error);
}
} catch (Exception e) {
e.printStackTrace();
}
request.setAttribute("CollapseKey", collapseKey);
request.setAttribute("Message", userMessage);
request.getRequestDispatcher("XX.jsp").forward(request, response);
}
}
Your payload (added to the Message by calls to addData) can only be name/value pairs. If you want to send a JSON, you can put a JSON string in the value of such name/value pair. Then you'll have to parse that JSON yourself in the client side.
For example :
.addData("message","{\"some_json_key\":\"some_json_value\"}")

Easy way to dynamically invoke web services (without JDK or proxy classes)

In Python I can consume a web service so easily:
from suds.client import Client
client = Client('http://www.example.org/MyService/wsdl/myservice.wsdl') #create client
result = client.service.myWSMethod("Bubi", 15) #invoke method
print result #print the result returned by the WS method
I'd like to reach such a simple usage with Java.
With Axis or CXF you have to create a web service client, i.e. a package which reproduces all web service methods so that we can invoke them as if they where normal methods. Let's call it proxy classes; usually they are generated by wsdl2java tool.
Useful and user-friendly. But any time I add/modify a web service method and I want to use it in a client program I need to regenerate proxy classes.
So I found CXF DynamicClientFactory, this technique avoids the use of proxy classes:
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.endpoint.dynamic.DynamicClientFactory;
//...
//create client
DynamicClientFactory dcf = DynamicClientFactory.newInstance();
Client client = dcf.createClient("http://www.example.org/MyService/wsdl/myservice.wsdl");
//invoke method
Object[] res = client.invoke("myWSMethod", "Bubi");
//print the result
System.out.println("Response:\n" + res[0]);
But unfortunately it creates and compiles proxy classes runtime, hence requires JDK on the production machine. I have to avoid this, or at least I can't rely on it.
My question:
Is there another way to dinamically invoke any method of a web service in Java, without having a JDK at runtime and without generating "static" proxy classes? Maybe with a different library? Thanks!
I know this is a really old question but if you are still interested you could use soap-ws github project: https://github.com/reficio/soap-ws
Here you have a sample usage really simple:
Wsdl wsdl = Wsdl.parse("http://www.webservicex.net/CurrencyConvertor.asmx?WSDL");
SoapBuilder builder = wsdl.binding()
.localPart("CurrencyConvertorSoap")
.find();
SoapOperation operation = builder.operation()
.soapAction("http://www.webserviceX.NET/ConversionRate")
.find();
Request request = builder.buildInputMessage(operation)
SoapClient client = SoapClient.builder()
.endpointUrl("http://www.webservicex.net/CurrencyConvertor.asmx")
.build();
String response = client.post(request);
As you can see it is really simple.
With CXF 3.x this could be possible with StaxDataBinding. Follow below steps to get the basics. Of course, this could be enhanced to your needs.
Create StaxDataBinding something like below. Note below code can be enhanced to your sophistication.
class StaxDataBinding extends AbstractInterceptorProvidingDataBinding {
private XMLStreamDataReader xsrReader;
private XMLStreamDataWriter xswWriter;
public StaxDataBinding() {
super();
this.xsrReader = new XMLStreamDataReader();
this.xswWriter = new XMLStreamDataWriter();
inInterceptors.add(new StaxInEndingInterceptor(Phase.POST_INVOKE));
inFaultInterceptors.add(new StaxInEndingInterceptor(Phase.POST_INVOKE));
inInterceptors.add(RemoveStaxInEndingInterceptor.INSTANCE);
inFaultInterceptors.add(RemoveStaxInEndingInterceptor.INSTANCE);
}
static class RemoveStaxInEndingInterceptor
extends AbstractPhaseInterceptor<Message> {
static final RemoveStaxInEndingInterceptor INSTANCE = new RemoveStaxInEndingInterceptor();
public RemoveStaxInEndingInterceptor() {
super(Phase.PRE_INVOKE);
addBefore(StaxInEndingInterceptor.class.getName());
}
public void handleMessage(Message message) throws Fault {
message.getInterceptorChain().remove(StaxInEndingInterceptor.INSTANCE);
}
}
public void initialize(Service service) {
for (ServiceInfo serviceInfo : service.getServiceInfos()) {
SchemaCollection schemaCollection = serviceInfo.getXmlSchemaCollection();
if (schemaCollection.getXmlSchemas().length > 1) {
// Schemas are already populated.
continue;
}
new ServiceModelVisitor(serviceInfo) {
public void begin(MessagePartInfo part) {
if (part.getTypeQName() != null
|| part.getElementQName() != null) {
return;
}
part.setTypeQName(Constants.XSD_ANYTYPE);
}
}.walk();
}
}
#SuppressWarnings("unchecked")
public <T> DataReader<T> createReader(Class<T> cls) {
if (cls == XMLStreamReader.class) {
return (DataReader<T>) xsrReader;
}
else {
throw new UnsupportedOperationException(
"The type " + cls.getName() + " is not supported.");
}
}
public Class<?>[] getSupportedReaderFormats() {
return new Class[] { XMLStreamReader.class };
}
#SuppressWarnings("unchecked")
public <T> DataWriter<T> createWriter(Class<T> cls) {
if (cls == XMLStreamWriter.class) {
return (DataWriter<T>) xswWriter;
}
else {
throw new UnsupportedOperationException(
"The type " + cls.getName() + " is not supported.");
}
}
public Class<?>[] getSupportedWriterFormats() {
return new Class[] { XMLStreamWriter.class, Node.class };
}
public static class XMLStreamDataReader implements DataReader<XMLStreamReader> {
public Object read(MessagePartInfo part, XMLStreamReader input) {
return read(null, input, part.getTypeClass());
}
public Object read(QName name, XMLStreamReader input, Class<?> type) {
return input;
}
public Object read(XMLStreamReader reader) {
return reader;
}
public void setSchema(Schema s) {
}
public void setAttachments(Collection<Attachment> attachments) {
}
public void setProperty(String prop, Object value) {
}
}
public static class XMLStreamDataWriter implements DataWriter<XMLStreamWriter> {
private static final Logger LOG = LogUtils
.getL7dLogger(XMLStreamDataWriter.class);
public void write(Object obj, MessagePartInfo part, XMLStreamWriter writer) {
try {
if (!doWrite(obj, writer)) {
// WRITE YOUR LOGIC HOW you WANT TO HANDLE THE INPUT DATA
//BELOW CODE JUST CALLS toString() METHOD
if (part.isElement()) {
QName element = part.getElementQName();
writer.writeStartElement(element.getNamespaceURI(),
element.getLocalPart());
if (obj != null) {
writer.writeCharacters(obj.toString());
}
writer.writeEndElement();
}
}
}
catch (XMLStreamException e) {
throw new Fault("COULD_NOT_READ_XML_STREAM", LOG, e);
}
}
public void write(Object obj, XMLStreamWriter writer) {
try {
if (!doWrite(obj, writer)) {
throw new UnsupportedOperationException("Data types of "
+ obj.getClass() + " are not supported.");
}
}
catch (XMLStreamException e) {
throw new Fault("COULD_NOT_READ_XML_STREAM", LOG, e);
}
}
private boolean doWrite(Object obj, XMLStreamWriter writer)
throws XMLStreamException {
if (obj instanceof XMLStreamReader) {
XMLStreamReader xmlStreamReader = (XMLStreamReader) obj;
StaxUtils.copy(xmlStreamReader, writer);
xmlStreamReader.close();
return true;
}
else if (obj instanceof XMLStreamWriterCallback) {
((XMLStreamWriterCallback) obj).write(writer);
return true;
}
return false;
}
public void setSchema(Schema s) {
}
public void setAttachments(Collection<Attachment> attachments) {
}
public void setProperty(String key, Object value) {
}
}
}
Prepare your input to match the expected input, something like below
private Object[] prepareInput(BindingOperationInfo operInfo, String[] paramNames,
String[] paramValues) {
List<Object> inputs = new ArrayList<Object>();
List<MessagePartInfo> parts = operInfo.getInput().getMessageParts();
if (parts != null && parts.size() > 0) {
for (MessagePartInfo partInfo : parts) {
QName element = partInfo.getElementQName();
String localPart = element.getLocalPart();
// whatever your input data you need to match data value for given element
// below code assumes names are paramNames variable and value in paramValues
for (int i = 0; i < paramNames.length; i++) {
if (paramNames[i].equals(localPart)) {
inputs.add(findParamValue(paramNames, paramValues, localPart));
}
}
}
}
return inputs.toArray();
}
Now set the proper data binding and pass the data
Bus bus = CXFBusFactory.getThreadDefaultBus();
WSDLServiceFactory sf = new WSDLServiceFactory(bus, wsdl);
sf.setAllowElementRefs(false);
Service svc = sf.create();
Client client = new ClientImpl(bus, svc, null,
SimpleEndpointImplFactory.getSingleton());
StaxDataBinding databinding = new StaxDataBinding();
svc.setDataBinding(databinding);
bus.getFeatures().add(new StaxDataBindingFeature());
BindingOperationInfo operInfo = ...//find the operation you need (see below)
Object[] inputs = prepareInput(operInfo, paramNames, paramValues);
client.invoke("operationname", inputs);
If needed you can match operation name something like below
private BindingOperationInfo findBindingOperation(Service service,
String operationName) {
for (ServiceInfo serviceInfo : service.getServiceInfos()) {
Collection<BindingInfo> bindingInfos = serviceInfo.getBindings();
for (BindingInfo bindingInfo : bindingInfos) {
Collection<BindingOperationInfo> operInfos = bindingInfo.getOperations();
for (BindingOperationInfo operInfo : operInfos) {
if (operInfo.getName().getLocalPart().equals(operationName)) {
if (operInfo.isUnwrappedCapable()) {
return operInfo.getUnwrappedOperation();
}
return operInfo;
}
}
}
}
return null;
}

Resources