Java connect to several SAP Systems via Jco - java

I am currently developing a small Java Application which needs to read some data from SAP.
Nearly everything is working fine.
I can connect to SAP, I can call a BAPI and get a result and I also can handle the given result. But....
I have two different SAP Systems (System A and System B).
If I start my application and make a connection to System A, everything is fine. But after all data from System A are handled I want to call System B (without stopping / restarting my application). In this situation I can't connect to System B.
I think there must be something wrong with the part where I establish the connection to my SAP System.
Can anybody tell my how to do this right?
This is my Code:
This is how I make a connection (SapLogOn and SapSystem are only wrapper classes for the needed parameters)
private void connectToSap(ISapLogOn logOn, ISapSystem system)
throws JCoException {
connectProperties = new Properties();
connectProperties.setProperty("ACTION", "CREATE");
connectProperties.setProperty(DestinationDataProvider.JCO_DEST, "POOL_DE");
connectProperties.setProperty(DestinationDataProvider.JCO_ASHOST, system.getAsHost());
connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR, system.getSysNr());
connectProperties.setProperty(DestinationDataProvider.JCO_CLIENT, system.getClient());
connectProperties.setProperty(DestinationDataProvider.JCO_USER, logOn.getUserName());
connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD, logOn.getPassword());
connectProperties.setProperty(DestinationDataProvider.JCO_LANG, system.getLanguage());
connectProperties.setProperty(DestinationDataProvider.JCO_SAPROUTER, system.getSapRouterString());
connectProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, system.getPoolCapacity());
connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, system.getPeakLimit());
MyDestinationDataProvider myProvider = new MyDestinationDataProvider();
if (!com.sap.conn.jco.ext.Environment
.isDestinationDataProviderRegistered()) {
com.sap.conn.jco.ext.Environment
.registerDestinationDataProvider(myProvider);
}
myProvider.changePropertiesForABAP_AS(connectProperties);
}
And here comes part two:
public class MyDestinationDataProvider implements DestinationDataProvider {
public static Logger LOGGER = Logger.getLogger(MyDestinationDataProvider.class.getName());
#SuppressWarnings("unused")
private DestinationDataEventListener eL;
private Hashtable<String, Properties> propertiesTab;
public MyDestinationDataProvider() {
this.propertiesTab = new Hashtable<String, Properties>();
this.eL = new DestinationDataEventListener() {
#Override
public void updated(String arg0) {}
#Override
public void deleted(String arg0) {}
};
}
public Properties getDestinationProperties(String destinationName)
{
if(propertiesTab.containsKey(destinationName)){
return propertiesTab.get(destinationName);
}
LOGGER.error("Destination " + destinationName + " is not available");
throw new RuntimeException("Destination " + destinationName + " is not available");
}
public void setDestinationDataEventListener(DestinationDataEventListener eventListener)
{
this.eL = eventListener;
}
public boolean supportsEvents()
{
return true;
}
void changePropertiesForABAP_AS(Properties pConProps)
{
if(pConProps.getProperty("ACTION").equalsIgnoreCase("CREATE")){
propertiesTab.put(pConProps.getProperty("jco.client.dest"), pConProps);
}
else if(pConProps.getProperty("ACTION").equalsIgnoreCase("DELETE")){
propertiesTab.remove(pConProps.getProperty("jco.client.dest"));
}
}
}
I use Java 6 and JCo3.
Regards LStrike

Related

Concurrency on Vertx

i have joined to one of those Vertx lovers , how ever the single threaded main frame may not be working for me , because in my server there might be 50 file download requests at a moment , as a work around i have created this class
public abstract T onRun() throws Exception;
public abstract void onSuccess(T result);
public abstract void onException();
private static final int poolSize = Runtime.getRuntime().availableProcessors();
private static final long maxExecuteTime = 120000;
private static WorkerExecutor mExecutor;
private static final String BG_THREAD_TAG = "BG_THREAD";
protected RoutingContext ctx;
private boolean isThreadInBackground(){
return Thread.currentThread().getName() != null && Thread.currentThread().getName().equals(BG_THREAD_TAG);
}
//on success will not be called if exception be thrown
public BackgroundExecutor(RoutingContext ctx){
this.ctx = ctx;
if(mExecutor == null){
mExecutor = MyVertxServer.vertx.createSharedWorkerExecutor("my-worker-pool",poolSize,maxExecuteTime);
}
if(!isThreadInBackground()){
/** we are unlocking the lock before res.succeeded , because it might take long and keeps any thread waiting */
mExecutor.executeBlocking(future -> {
try{
Thread.currentThread().setName(BG_THREAD_TAG);
T result = onRun();
future.complete(result);
}catch (Exception e) {
GUI.display(e);
e.printStackTrace();
onException();
future.fail(e);
}
/** false here means they should not be parallel , and will run without order multiple times on same context*/
},false, res -> {
if(res.succeeded()){
onSuccess((T)res.result());
}
});
}else{
GUI.display("AVOIDED DUPLICATE BACKGROUND THREADING");
System.out.println("AVOIDED DUPLICATE BACKGROUND THREADING");
try{
T result = onRun();
onSuccess((T)result);
}catch (Exception e) {
GUI.display(e);
e.printStackTrace();
onException();
}
}
}
allowing the handlers to extend it and use it like this
public abstract class DefaultFileHandler implements MyHttpHandler{
public abstract File getFile(String suffix);
#Override
public void Handle(RoutingContext ctx, VertxUtils utils, String suffix) {
new BackgroundExecutor<Void>(ctx) {
#Override
public Void onRun() throws Exception {
File file = getFile(URLDecoder.decode(suffix, "UTF-8"));
if(file == null || !file.exists()){
utils.sendResponseAndEnd(ctx.response(),404);
return null;
}else{
utils.sendFile(ctx, file);
}
return null;
}
#Override
public void onSuccess(Void result) {}
#Override
public void onException() {
utils.sendResponseAndEnd(ctx.response(),404);
}
};
}
and here is how i initialize my vertx server
vertx.deployVerticle(MainDeployment.class.getCanonicalName(),res -> {
if (res.succeeded()) {
GUI.display("Deployed");
} else {
res.cause().printStackTrace();
}
});
server.requestHandler(router::accept).listen(port);
and here is my MainDeployment class
public class MainDeployment extends AbstractVerticle{
#Override
public void start() throws Exception {
// Different ways of deploying verticles
// Deploy a verticle and don't wait for it to start
for(Entry<String, MyHttpHandler> entry : MyVertxServer.map.entrySet()){
MyVertxServer.router.route(entry.getKey()).handler(new Handler<RoutingContext>() {
#Override
public void handle(RoutingContext ctx) {
String[] handlerID = ctx.request().uri().split(ctx.currentRoute().getPath());
String suffix = handlerID.length > 1 ? handlerID[1] : null;
entry.getValue().Handle(ctx, new VertxUtils(), suffix);
}
});
}
}
}
this is working just fine when and where i need it , but i still wonder if is there any better way to handle concurencies like this on vertx , if so an example would be really appreciated . thanks alot
I don't fully understand your problem and reasons for your solution. Why don't you implement one verticle to handle your http uploads and deploy it multiple times? I think that handling 50 concurrent uploads should be a piece of cake for vert.x.
When deploying a verticle using a verticle name, you can specify the number of verticle instances that you want to deploy:
DeploymentOptions options = new DeploymentOptions().setInstances(16);
vertx.deployVerticle("com.mycompany.MyOrderProcessorVerticle", options);
This is useful for scaling easily across multiple cores. For example you might have a web-server verticle to deploy and multiple cores on your machine, so you want to deploy multiple instances to take utilise all the cores.
http://vertx.io/docs/vertx-core/java/#_specifying_number_of_verticle_instances
vertx is a well-designed model so that a concurrency issue does not occur.
generally, vertx does not recommend the multi-thread model.
(because, handling is not easy.)
If you select multi-thread model, you have to think about shared data..
Simply, if you just only want to split EventLoop Area,
first of all, you make sure Check your a number of CPU Cores.
and then Set up the count of Instances .
DeploymentOptions options = new DeploymentOptions().setInstances(4);
vertx.deployVerticle("com.mycompany.MyOrderProcessorVerticle", options);
But, If you have 4cores of CPU, you don't set up over 4 instances.
If you set up to number four or more, the performance won't improve.
vertx concurrency reference
http://vertx.io/docs/vertx-core/java/

How to register remote object with RMI registry?

I'm trying to get these Java RMI Trails from the Oracle tutorials to work but I can't seem to. I keep getting the following error when trying to start the server:
java.security.AccessControlException: access denied ("java.net.SocketPermission"
"127.0.0.1:1099" "connect,resolve")
The trace point to the invokation of registry.rebind(name, stub);
The project is a Server application to which one can send Tasks (a remote interface) and provides a Remote interface Compute, to preform this task. The Client side of the application provides an implementation of Task that calculates Pi.
When trying to follow this I've set up two projects 'ComputeEngine' and 'ComputeClient' as:
Where 'compute.jar' contains the interfaces Compute and Task.
I did do: 'start rmiregistry' before attempting to start the server (not sure I hade to before I started the client though).
Any hints as to what is going worng? Does it have anything to do with security policies, I'm not sure I understand what they do?
The code can be found in the link provided too but I'll post it here as well:
ComputeEngine.java
public class ComputeEngine implements Compute {
public ComputeEngine() {
super();
}
public <T> T executeTask(Task<T> t) {
return t.execute();
}
public static void main(String[] args) {
if (System.getSecurityManager() == null) {
System.setSecurityManager(new SecurityManager());
}
try {
String name = "Compute";
Compute engine = new ComputeEngine();
Compute stub =
(Compute) UnicastRemoteObject.exportObject(engine, 0);
Registry registry = LocateRegistry.getRegistry();
registry.rebind(name, stub); // <-- This is where the error points.
System.out.println("ComputeEngine bound");
} catch (Exception e) {
System.err.println("ComputeEngine exception:");
e.printStackTrace();
}
}
}
Compute.java
public interface Compute extends Remote {
<T> T executeTask(Task<T> t) throws RemoteException;
}
Task.java
public interface Task<T> {
T execute();
}
CopmutePi.java
public class ComputePi {
public static void main(String args[]) {
if (System.getSecurityManager() == null) {
System.setSecurityManager(new SecurityManager());
}
try {
String name = "Compute";
Registry registry = LocateRegistry.getRegistry(args[0]);
Compute comp = (Compute) registry.lookup(name);
Pi task = new Pi(Integer.parseInt(args[1]));
BigDecimal pi = comp.executeTask(task);
System.out.println(pi);
} catch (Exception e) {
System.err.println("ComputePi exception:");
e.printStackTrace();
}
}
}
Pi.java
public class Pi implements Task<BigDecimal>, Serializable {
private static final long serialVersionUID = 227L;
private static final BigDecimal FOUR =
BigDecimal.valueOf(4);
private static final int roundingMode =
BigDecimal.ROUND_HALF_EVEN;
private final int digits;
public Pi(int digits) {
this.digits = digits;
}
public BigDecimal execute() {
return computePi(digits);
}
public static BigDecimal computePi(int digits) {
// computing Pi...
}
}
Get rid of the security manager and the codebase feature and try again. You only need the security manager if you use the codebase feature, and you only need the codebase feature if you're going to use it to deploy your application with. It is optional and generally not used, at least at tutorial stage.

How to know: How many requests is HttpServer-in-Vertx serving

I write a server with Vertx.
I have about 40k users. I can print every request but I don't know how to know how many current requests my server is serving
I used this class: http://vertx.io/docs/apidocs/io/vertx/core/http/HttpServer.html but this is no method to do it
Vertx is great toolkit but it can not show server status, really????
My server code:
public class MyFirstVerticle extends AbstractVerticle {
private HttpServer httpServer = null;
#Override
public void start() throws Exception {
httpServer = vertx.createHttpServer();
httpServer.requestHandler(new Handler<HttpServerRequest>() {
#Override
public void handle(HttpServerRequest request) {
String path = request.path();
System.out.println("incoming request: [" + request.remoteAddress() + "] at " + path);
}
});
httpServer.listen(9999);
}
}
Since vert.x 3.x.x http://vertx.io/docs/vertx-dropwizard-metrics is an official component of vert.x
I think what you search is this:
http://vertx.io/docs/vertx-dropwizard-metrics/java/#http-server-metrics
There are several possibilities to view the metrics
jmx http://vertx.io/docs/vertx-dropwizard-metrics/java/#jmx
http bridge for jmx http://vertx.io/docs/vertx-dropwizard-metrics/java/#_using_jolokia_and_hawtio
In our project we write periodically to a log file and send it in parallel to a graphite / grafana instance over udp
Vert.x requests are very short lived, so basing calculations solely on number of requests per second is not optimal. But, for the sake of discussion, you can achieve what you want in the following way:
public class MyFirstVerticle extends AbstractVerticle {
private HttpServer httpServer = null;
// Bad, done for the sake of simplicity
public final static AtomicInteger counter = new AtomicInteger(0);
#Override
public void start() throws Exception {
httpServer = vertx.createHttpServer();
httpServer.requestHandler(new Handler<HttpServerRequest>() {
public void handle(HttpServerRequest request) {
counter.incrementAndGet();
String path = request.path();
System.out.println("incoming request: [" + request.remoteAddress() + "] at " + path);
request.response().end();
request.endHandler(new Handler<Void>() {
#Override
public void handle(Void aVoid) {
counter.decrementAndGet();
}
});
}
});
httpServer.listen(9999);
}
}
Then to test yourself you can try something like that:
public class Main {
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
MyFirstVerticle verticle = new MyFirstVerticle();
vertx.deployVerticle(verticle);
// Very bad, but our request are very short
vertx.setPeriodic(1, new Handler<Long>() {
#Override
public void handle(Long aLong) {
// Otherwise will overflow our console
if (MyFirstVerticle.counter.intValue() > 0) {
System.out.println(MyFirstVerticle.counter.intValue());
}
}
});
}
}

Cling with tomcat

I am trying to create a service to autodiscover upnp devices in my local network, implementing it in a webapplication running on tomcat 7 and using 4thline Cling library.
I got this error
org.fourthline.cling.transport.RouterImpl handleStartFailure
SEVERE: Unable to initialize network router: org.fourthline.cling.transport.spi.InitializationException: Failed to set modified URLStreamHandlerFactory in this environment. Can't use bundled default client based on HTTPURLConnection, see manual.
In the cling's manual they say that Cling couldn't use the Java JDK's HTTPURLConnection for HTTP client operations. They suggest to configure network transport.
I didn't understand well how to do. Anyone had a similar problem?
Can you suggest me an example?
Thanks.
The code I am using is:
public class Example {
public static void startDiscovery() {
RegistryListener listener = new RegistryListener() {
public void remoteDeviceDiscoveryStarted(Registry registry,RemoteDevice device) {
String name = device.getDisplayString();
String url = device.getDetails().getBaseURL().toString();
String friendlyName = device.getDetails().getFriendlyName();
}
public void remoteDeviceDiscoveryFailed(Registry registry,RemoteDevice device, Exception ex) {
}
public void remoteDeviceAdded(Registry registry, RemoteDevice device) {
}
public void remoteDeviceUpdated(Registry registry,RemoteDevice device) {
}
public void remoteDeviceRemoved(Registry registry,RemoteDevice device) {
}
public void localDeviceAdded(Registry registry, LocalDevice device) {
}
public void localDeviceRemoved(Registry registry, LocalDevice device) {
}
public void beforeShutdown(Registry registry) {
}
public void afterShutdown() {
}
};
try{
UpnpService upnpService = new UpnpServiceImpl(listener);
upnpService.getControlPoint().search(new STAllHeader());
// wait 5 seconds for them to respond
Thread.sleep(5000);
upnpService.shutdown();
}catch(Exception e){
e.printStackTrace();
}
}
}

Can't configure node_auto_index with InProcessServer() SDN 4

I'm using the following java configuration for my Neo4j (using SDN 4.0.0.RELEASE) based application, with unit tests:
...
#Bean
public Neo4jServer neo4jServer() {
return new InProcessServer();
}
#Bean
public SessionFactory getSessionFactory() {
Neo4jRequest<String> neo4jRequest = new DefaultRequest(httpClient);
String json = "{" + "\"name\" : \"node_auto_index\", " + "\"config\" : {" + "\"type\" : \"fulltext\", "
+ "\"provider\" : \"lucene\"" + "}" + "}";
neo4jRequest.execute(neo4jServer().url() + "db/data/index/node/", json);
return new SessionFactory("org.myproject.domain");
}
...
I created on getSessionFactory() a full-text node_auto_index. I'm actually missing how to configure my current in-memory istance of Neo4j, because I need to set those properties:
node_auto_indexing=true
node_keys_indexable=title
I read on "Good Relationships: The Spring Data Neo4j Guide Book" that
InProcessServer is useful for test and development environments, but is not recommended for production use. This implementation will start a new instance of CommunityNeoServer running on an available local port and return the URL needed to connect to it.
Do I need to use CommunityNeoServer instead? Should I use it even if it's deprecated? In this case, how can I configure it for an in-memory database that will support node auto indexing?
If you want to supply additional configuration, you can provide your own implementation of Neo4jServer, like this:
public class AutoIndexTestServer implements Neo4jServer {
final String uri;
public AutoIndexTestServer() {
try {
ServerControls controls = TestServerBuilders.newInProcessBuilder()
.withConfig("dbms.security.auth_enabled", "false")
.withConfig("node_auto_indexing", "true")
.withConfig("node_keys_indexable", "title")
.newServer();
uri = controls.httpURI().toString();
}
catch (Exception e) {
throw new RuntimeException("Could not start inprocess server",e);
}
}
#Override
public String url() {
return uri;
}
#Override
public String username() {
return null;
}
#Override
public String password() {
return null;
}
}
and use it
#Bean
public Neo4jServer neo4jServer() {
return new AutoIndexTestServer();
}

Categories

Resources