WebLogic ClassCastException during RMI - weblogic

So I setup two remote WebLogic applications to use RMI to communicate with each other.
The LocalServiceAPI.java file is located in the same package in the client & the host.
The same code works on my local machine on a test server, but does not on my company's unix server.
Both server versions are 12.1.3.0.0
The oddest thing: the narrow is successful, but the cast throws the classCastException.
Hashtable<String,String> env = new Hashtable<String,String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
env.put(Context.PROVIDER_URL, "t3://" + address + ":" + port);
Object obj = PortableRemoteObject.narrow(new InitialContext(env).lookup("LocalServiceAPI"), LocalServiceAPI.class);
return (LocalServiceAPI) obj;
Exception:
java.lang.ClassCastException: com.cleargoals.service.LocalServiceAPIImpl_12130_WLStub cannot be cast to com.cleargoals.service.LocalServiceAPI

Since your server version is 12.1.3. So I assume it is EJB3 compliant server. For EJb3, context.lookup method call assumes parameter passed is an global JDNI name of remote class...So ensure u r passing global JNDI name of remote class in lookup call...Read link if you are not sure what is meant by global word in JNDI name...Secondly, since EJB2, you are not required to use PortableRemoteObject.narrow method, the lookup call itself does the work for you...its explanation is also in same link.

Related

How to use CLNTCONN channels in AMQCLCHL.TAB file from a Vb.net application

In my Vb.net application I'm using IBM MQ v7.5 Managed client connection to connect to a queue manager. Until now I have provided channel name and host name in a .Config file and call the following:
MQQueueManager(Qmanagername, Channel, Host)
But Now I have a AMQCLCHL.TAB file with the channel details. How can I have my Vb.net application use the channel name and host name from the AMQCLCHL.TAB file.
You need to let the application know the location of the channel table file. The IBM Knowledge center shows this can be done in three ways with managed client connection type:
Using the .NET application configuration file. In the CHANNELS section, use the keys ChannelDefinitionDirectory to specify the directory where the table is located, and ChannelDefinitionFile to specify the file name.
Using the environment variables MQCHLLIB to specify the directory where the table is located, and MQCHLTAB to specify the file name of the table.
Using the client configuration file. In the CHANNELS stanza, use the attributes ChannelDefinitionDirectory to specify the directory where the table is located, and ChannelDefinitionFile to specify the file name.
You can then change your call to drop the channel and hostname and it will pickup the channel table that you specified using one of the three ways described above.
New MQQueueManager(Qmanagername)
Update to include additional information from the comments
If your application runs on the same server as the queue manager it will by default connect in unmanaged mode using server bindings if you do not force it to use client mode. This is described in detail in the Knowledge Center.
You can force it to a client mode by setting the environment variable NMQ_MQ_LIB.
For unmanaged MQ client mode use NMQ_MQ_LIB=mqic.dll
For managed client mode use NMQ_MQ_LIB=managed
The MQC.TRANSPORT_PROPERTY hashtable property can also used to force it to use client mode.
Unmanaged MQ client mode example:
Hashtable properties = new Hashtable();
properties.Add(MQC.TRANSPORT_PROPERTY, "MQC.TRANSPORT_MQSERIES_CLIENT");
return new MQQueueManager(queueManagerName, properties);
Managed MQ client mode example:
Hashtable properties = new Hashtable();
properties.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED");
return new MQQueueManager(queueManagerName, properties);

How to manually set/propagate security context information e.g. Principal for JBoss 7 (over JBoss remoting 2)

I'm using jboss remoting 2.5.4.SP3 to provide remote access to EJBs in a JBoss 7.1 server from both a web app and other JBoss instances. I'm doing it manually because of issues with remote EJB access in JBoss 7.1, specifically (but not only) the inability to access the same (interface) bean on multiple servers simultaneously. I'm using remoting2 because remoting3 has no documentation.
I have remoting working using TransporterHandle/TransporterClient using the socket transport, but in methods called via this remote connection, the server wants to lookup the principal from the ejbContext. I can't find a way to manually set the principal, or other contextual security/identity information. At the limit I'd be happy just to set the principal when the ejb method is invoked - all incoming calls are to local EJB3 beans - or even to set it specifically for the EJBContext.
I've found a lot of information regarding Spring (which I'm not using), but nothing seems to match my particular context.
And now, the correct way to do this:
On the client side I get the security context and package up the security domain and subject info for transport to the server along with the invocation. The SecurityDomain is a String and SubjectInfo is serializable:
Map m = new HashMap();
SecurityContext securityContext = SecurityContextAssociation.getSecurityContext();
if (securityContext != null) {
m.put("SUBJECT-INFO", securityContext.getSubjectInfo());
m.put("SECURITY-DOMAIN", securityContext.getSecurityDomain());
}
response = remotingClient.invoke(request, m);
The map m gets sent with the invocation over jboss remoting. On the server side, I extract the security information and set the context for the invocation like this:
SecurityContext oldContext = SecurityContextAssociation.getSecurityContext();
SubjectInfo si = (SubjectInfo) invocation.getRequestPayload().get("SUBJECT-INFO");
String domain = (String) invocation.getRequestPayload().get("SECURITY-DOMAIN");
if (si != null) {
SecurityContext sc = new JBossSecurityContext(domain);
sc.setSubjectInfo(si);
SecurityContextAssociation.setSecurityContext(sc);
}
try {
return super.invoke(invocation);
} finally {
SecurityContextAssociation.setSecurityContext(oldContext);
}
Works like a charm!
Have a look at the jboss-ejb-client.properties. There is also a quickstart example using a remote client to lookup an EJB.
I've solved my underlying problem, although not in the general way I was hoping for.
I put a servlet filter on all incoming requests, recording request.getUserPrincipal in a thread local. I can then access this in non-EE code and find the principal making the request. Then when I make call to my app server I use JBoss Remoting's ability to attach metadata to each invocation to pass the Principal over the wire. I had to copy the TransporterClient to do this because it's private constructors et al don't allow for overriding the functionality required to attach per-request metadata (as opposed to per-connection). On the server side I take the incoming Principal and set it into a thread local. Then, in subsequent code that accesses EJBContext.getCallerPrincipal I also lookup the incoming Principal from the thread local, and if that isn't null (hence we are in a remote EJB call), I use that if the caller principal is anonymous. If it's not anonymous then it must have been set in some way after the incoming call, so I ignore the incoming Principal in that case.
All in all, a much more specialised solution than I was hoping for, and it doesn't shed any light on how I can do generic context propagation in JBoss 7.1 over the wire.

Differences in calling JMX MBean remotely or from servlet deployed in the same JVM

I have several applications deployed on WebLogic server. Those applications expose some JMX MBeans. When I call operations on those MBeans remotely through JConsole or JRMC, they work fine.
But since JMX is not really firewall-friendly I have created another simple Servlet application that is deployed on the same server and that invokes operations on a set local MBeans. From within servlet I use ManagementFactory.getPlatformMBeanServer() to find and call MBeans of other applications deployed in the same JVM, but for some operations I get either ClassCastException or ClassNotFoundException depending on the operation that is called, but some operations work fine.
Any ideas?
I suspect what is happening here is that your servlet thread has a context classloader that is different from that of the MBeans that you are invoking against. Consequently, if the MBean attributes, operation parameters or return values contain types that are not core JVM classes (or classes not shared from the same root classloader), you will get ClassCast, ClassNotFound and ClassDefNotFound Exceptions.
This procedure may work for you. What you need to do is temporarily change the context classloader of the servlet thread to the same classloader as the MBean was loaded from. Once the invocation is complete, you set it back again. Since you know the ObjectName of the target MBean, the MBeanServer will supply you the correct classloader.
Here's a basic example:
public void callMBean() throws MalformedObjectNameException, NullPointerException, InstanceNotFoundException {
final ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
try {
ObjectName targetObjectName = new ObjectName(".....");
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ClassLoader tmpClassLoader = server.getClassLoaderFor(targetObjectName);
Thread.currentThread().setContextClassLoader(tmpClassLoader);
// ==========================================
// Invoke operations here
// ==========================================
} finally {
Thread.currentThread().setContextClassLoader(currentClassLoader);
}
}

remote ejb call trapped in the lookup in linux server

I'm using glassfish 3.1.1 with an application client container called via java web start.
My program is not working , it remain glued in the lookup() and never pass it .
Context c = new InitialContext()
geo = (GeoBeanRemote) c.lookup("java:global/server_side/server-ejb/GeoBean");
System.out.println("end lookup");
I have already tested this in a windows server and it worked perfelcty but now , in the production server (ubuntu 11.04) it doesn't .
How can i fix this ?
Thanks.
It sounds like you might be having some routing issues. I suggest verifying your RMI port is open. The default is 3700.

EJB lookup problem

I have a Glassfish v2.1.1 cluster setup. I deployed an EAR file consisting a single stateless bean to stand alone server. It has an IIOP port 3752.
My client application which will be communicating with this bean is deployed on cluster. When i lookup bean's name, i get NameNotFoundException. Code looks as below:
Properties props = new Properties();
props.setProperty("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");
props.setProperty("java.naming.factory.url.pkgs", "com.sun.enterprise.naming");
props.setProperty("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
if (logger.isDebugEnabled()) {
logger.debug("Looking for bean from location : " + PropertiesService.instance().getSchedulerOrbHost() + ":"
+ PropertiesService.instance().getSchedulerOrbPort());
}
props.setProperty("org.omg.CORBA.ORBInitialHost", PropertiesService.instance().getSchedulerOrbHost());
props.setProperty("org.omg.CORBA.ORBInitialPort", PropertiesService.instance().getSchedulerOrbPort());
InitialContext context = null;
try {
context = new InitialContext(props);
} catch (NamingException e) {
e.printStackTrace();
}
String beanName = "test.OperationControllerRemote";
OperationControllerRemote remote = (OperationControllerRemote) context.lookup(beanName);
Note that i checked JNDI tree and name "test.OperationControllerRemote" is there.
Any opinions please?
Here are the ways I have got it to work with a GF 2.1.1 cluster and a Swing client. I'm currently going with the Standalone option because of client launch speed, but the ACC might work for you.
Standalone
The way you're doing it is considered standalone.
http://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#StandaloneRemoteEJB
http://blogs.oracle.com/dadelhardt/entry/standalone_iiop_clients_with_glassfish
ACC
Another way to approach this is to launch the client with the ACC. This means packaging the client code into the ear as an Application Client and either launching using the JNLP method or manually installing a bundled ACC (mini glassfish really) on client machines. In GF 2.1, either way works ok, but both are pretty fat and JNLP method can make startup times a bit longer. Supposedly in GF 3.1 they've reworked the ACC and it starts up faster. Something that may not be obvious is that with the ACC you get the list of servers in the cluster provided automatically at client startup.
http://blogs.oracle.com/theaquarium/entry/java_ee_clients_with_or
http://download.oracle.com/docs/cd/E18930_01/html/821-2418/beakv.html#scrolltoc
http://download.oracle.com/docs/cd/E18930_01/html/821-2418/gkusn.html
Lookups
Either of the above ways provides RMI/CORBA failover and load balancing for the client.
Either way, when you have the right dependencies on your classpath and the com.sun.appserv.iiop.endpoints system property set (like node1:33700,node2:33701), you'll only need the no-args InitialContext because Glassfish's stuff autoregisters their connection properties, etc as described in the first link:
new InitialContext()
And lookups will work. For my remote session beans (EJB 3.0) I typically do it like:
#Stateless(mappedName="FooBean")
public class FooBean implements FooBeanRemote {}
#Remote
public interface FooBeanRemote {}
then in client code:
FooBeanRemote foo = (FooBeanRemote) ctx.lookup("FooBean");