Ok, the case is simple. I need to be able to enable/disable logging for a JDK class (HttpURLConnection) programmatically.
public class HttpLoggingTest {
/**
Just a dummy to get some action from HttpURLConnection
*/
private static void getSomething(String urlStr) throws MalformedURLException, IOException {
System.out.println("----- " + urlStr);
HttpURLConnection conn = (HttpURLConnection) new URL("http://www.google.com").openConnection();
for (Entry<String, List<String>> header : conn.getHeaderFields().entrySet()) {
System.out.println(header.getKey() + "=" + header.getValue());
}
conn.disconnect();
}
public static void main(String[] args) throws MalformedURLException, IOException {
// HERE : Enable JDK logging for class
// sun.net.www.protocol.http.HttpURLConnection
getSomething("http://www.goodle.com");
// HERE: Disable JDK logging for class
// sun.net.www.protocol.http.HttpURLConnection
getSomething("http://www.microsoft.com");
}
}
In other words: before the first URL call the logging must be enabled and then disabled before the next call.
That is the challenge !
I'm unable to figure out how to do it.
Must work with Java 7.
Note:
I can do it by using configuration file, logging.properties :
sun.net.www.protocol.http.HttpURLConnection.level = ALL
but I want to have a programmatic solution.
UPDATE
Here's code that works in Java 6 but not in Java 7:
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Map.Entry;
import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
public class HttpLoggingTest {
/**
Just a dummy to get some action from HttpURLConnection
*/
private static void getSomething(String urlStr) throws MalformedURLException, IOException {
System.out.println("----- " + urlStr);
HttpURLConnection conn = (HttpURLConnection) new URL("http://www.google.com").openConnection();
for (Entry<String, List<String>> header : conn.getHeaderFields().entrySet()) {
System.out.println(header.getKey() + "=" + header.getValue());
}
conn.disconnect();
}
private static void enableConsoleHandler() {
//get the top Logger
Logger topLogger = java.util.logging.Logger.getLogger("");
// Handler for console (reuse it if it already exists)
Handler consoleHandler = null;
//see if there is already a console handler
for (Handler handler : topLogger.getHandlers()) {
if (handler instanceof ConsoleHandler) {
//found the console handler
consoleHandler = handler;
break;
}
}
if (consoleHandler == null) {
//there was no console handler found, create a new one
consoleHandler = new ConsoleHandler();
topLogger.addHandler(consoleHandler);
}
consoleHandler.setLevel(Level.ALL);
}
public static void main(String[] args) throws MalformedURLException, IOException {
enableConsoleHandler();
final Logger httpLogger = Logger.getLogger("sun.net.www.protocol.http.HttpURLConnection");
// Enable JDK logging for class
//sun.net.www.protocol.http.HttpURLConnection
httpLogger.setLevel(java.util.logging.Level.FINE);
getSomething("http://www.goodle.com");
// Disable JDK logging for class
// sun.net.www.protocol.http.HttpURLConnection
httpLogger.setLevel(java.util.logging.Level.INFO);
getSomething("http://www.microsoft.com");
}
}
UPDATE2
In order to make sure that a solution only enables output from our target class (and not all sorts of other JDK internal classes) I've created this minimal JAXB example. Here JAXB is simply an example of 'something else', it could have been any other part of the JDK that also use PlatformLogger.
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* Minimal dummy JAXB example. Only purpose is to provoke
* some JAXB action. Non-prod quality!
*/
#XmlRootElement(name = "book")
public class Celebrity {
#XmlElement
public String getFirstName() {
return "Marilyn";
}
#XmlElement
public String getLastName() {
return "Monroe";
}
public void printXML() {
JAXBContext context;
try {
context = JAXBContext.newInstance(Celebrity.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(this, System.out);
} catch (JAXBException ex) {
}
}
}
Instantiate an instance of the Celebrity class and call printXML(). Put that into getSomething() method. This must not generate JAXB internal logging output ... or else you've enabled logging for more than you thought.
Stumbled over PlatformLoggingMXBean the other day. I'll need to try something like:
PlatformLoggingMXBean platformLoggingMXBean =
ManagementFactory.getPlatformMXBean(PlatformLoggingMXBean.class);
platformLoggingMXBean.setLoggerLevel(
"sun.net.www.protocol.http.HttpURLConnection", "FINE");
and see it it works.
Try:
java.util.logging.Logger logger =
java.util.logging.Logger.getLogger(
"sun.net.www.protocol.http.HttpURLConnection");
logger.setLevel(java.util.logging.Level.FINE);
Related
I would like to know if there is a better way (without reflection) to get the java.security.Permissions for a specific URL and Role.
for example:
boolean canAccess = SecurityController.isAllowedToAccessUrl("/pages/confirmOrders.action", Collections.singletonList(new UserPrincipal("Dave")));
would work with the following constraint (web.xml):
<security-constraint>
<web-resource-collection>
<web-resource-name></web-resource-name>
<url-pattern>/pages/confirmOrders.action</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>Dave</role-name>
</auth-constraint>
The code, I wrote bellow works well. What I don't like is that I have to use reflection to invoke getContextPolicy from DelegatingPolicy.getInstance() and invoke getPermissionsForRole from ContextPolicy.
import org.jboss.security.jacc.ContextPolicy;
import org.jboss.security.jacc.DelegatingPolicy;
import javax.security.jacc.PolicyConfigurationFactory;
import javax.security.jacc.PolicyContext;
import javax.security.jacc.PolicyContextException;
import javax.security.jacc.WebResourcePermission;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.Permissions;
import java.security.Principal;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
public class SecurityController {
private static final Logger LOG = Logger.getLogger(SecurityController.class.getName());
static boolean isAllowedToAccessUrl(final String url, final List<Principal> principalRoles) {
initializeConfigurationInService();
boolean result = false;
for (Principal principalRole : principalRoles) {
try{
final ContextPolicy contextPolicy = getContextPolicy();
final Permissions permissions = getPermissionsFromContextPolicy(contextPolicy, principalRole.getName());
result |= permissions.implies(new WebResourcePermission(url, new String[] {"GET","POST"}));
}catch (Exception e){
LOG.log(Level.SEVERE, "checkAllowed failed checking if : ", e);
}
}
return result;
}
private static void initializeConfigurationInService() {
try {
final PolicyConfigurationFactory policyConfigurationFactory = PolicyConfigurationFactory.getPolicyConfigurationFactory();
policyConfigurationFactory.getPolicyConfiguration(PolicyContext.getContextID(), false);
} catch (PolicyContextException | ClassNotFoundException e) {
LOG.log(Level.INFO, "initializeConfigurationInService", e);
}
}
private static Permissions getPermissionsFromContextPolicy(ContextPolicy contextPolicy, String loginName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
final Method getPermissionsForRole = contextPolicy.getClass().getDeclaredMethod("getPermissionsForRole", String.class);
getPermissionsForRole.setAccessible(true);
return (Permissions) getPermissionsForRole.invoke(contextPolicy, loginName);
}
private static ContextPolicy getContextPolicy() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
final DelegatingPolicy delegatingPolicy = DelegatingPolicy.getInstance();
final Method getContextPolicy = delegatingPolicy.getClass().getDeclaredMethod("getContextPolicy", String.class);
getContextPolicy.setAccessible(true);
return (ContextPolicy) getContextPolicy.invoke(delegatingPolicy, PolicyContext.getContextID());
}
}
I read programmatically retrieve security constraints from web.xml but found it not very useful.
Any comments, ideas are really welcome. Thanks!
A similar standard method to do the 'isAllowedToAccessUrl` function is available in Java EE 8.
boolean hasAccessToWebResource(String resource, String... methods)
Checks whether the caller has access to the provided "web resource"
using the given methods, as specified by section 13.8 of the Servlet
specification. A caller has access if the web resource is either not
protected (constrained), or when it is protected by a role and the
caller is in that role.
See: SecurityContext#hasAccessToWebResource
Thanks to the comment of Uux I was able to shorten my code and get rid of using reflection. I am now able to verify if a specific role is allowed to access a specific URL in my code.
workable code below:
import javax.security.jacc.WebResourcePermission;
import java.security.CodeSource;
import java.security.Policy;
import java.security.Principal;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
public class SecurityController {
private static final Logger LOG = Logger.getLogger(SecurityController.class.getName());
static boolean isAllowedToAccessUrl(final String url, final List<Principal> principalRoles) {
try {
final CodeSource codesource = new CodeSource(null, (Certificate[]) null);
final Principal[] principals = principalRoles.toArray(new Principal[0]);
final ProtectionDomain domain = new ProtectionDomain(codesource, null, null, principals);
return Policy.getPolicy().implies(domain, (new WebResourcePermission(url, new String[] {"GET", "POST"})));
} catch (Exception e) {
LOG.log(Level.SEVERE, "checkAllowed failed checking if : ", e);
}
return false;
}
}
I am generating java source code using JCodeModel. I would to add copyright information to the generated code. Is this possible currently?
I tried using javadoc()in JDefinedClass , it adds the information only above the class definition.
com.sun.codemodel.writer.PrologCodeWriter is exactly what you are looking for
You can create a CodeWriter that writes the copyright header. This CodeWriter can delegate to another one - namely, to the one that you would usually pass to the CodeModel#build method.
A complete example:
import java.io.IOException;
import java.io.OutputStream;
import com.sun.codemodel.CodeWriter;
import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JPackage;
import com.sun.codemodel.writer.SingleStreamCodeWriter;
public class HeaderInCodeModel
{
public static void main(String[] args) throws Exception
{
JCodeModel codeModel = new JCodeModel();
codeModel._class("com.example.Example");
CodeWriter codeWriter = new SingleStreamCodeWriter(System.out);
String header = "// Copyright 2017 - example.com\n";
CodeWriter codeWriterWithHeader =
createCodeWriterWithHeader(header, codeWriter);
codeModel.build(codeWriterWithHeader);
}
private static CodeWriter createCodeWriterWithHeader(
String header, CodeWriter delegate)
{
CodeWriter codeWriter = new CodeWriter()
{
#Override
public OutputStream openBinary(JPackage pkg, String fileName)
throws IOException
{
OutputStream result = delegate.openBinary(pkg, fileName);
if (header != null)
{
result.write(header.getBytes());
}
return result;
}
#Override
public void close() throws IOException
{
delegate.close();
}
};
return codeWriter;
}
}
The resulting class will be
// Copyright 2017 - example.com
package com.example;
public class Example {
}
I try to run a websocket server in a Java project that was running on Tomcat6. I have set up a Tomcat 7 server where the project now is running on.
First I tried to run the socket example of Tomcat7. This run perfectly. I copied this class to my old project. When I run the old project again all the functionalities are working like before but only the websocket server doe not work.
This is the ChatAnnotation class that I have copied from the examples from Tomcat to my old project.
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.apache.log4j.Logger;
#ServerEndpoint(value = "/websocket/chat")
public class ChatAnnotation {
private static Logger logger = Logger.getLogger(ChatAnnotation.class);
private static final String GUEST_PREFIX = "Guest";
private static final AtomicInteger connectionIds = new AtomicInteger(0);
private static final Set<ChatAnnotation> connections = new CopyOnWriteArraySet<ChatAnnotation>();
private final String nickname;
private Session session;
public ChatAnnotation() {
nickname = GUEST_PREFIX + connectionIds.getAndIncrement();
logger.info("ws instance");
}
#OnOpen
public void start(Session session) {
this.session = session;
connections.add(this);
String message = String.format("* %s %s", nickname, "has joined.");
broadcast(message);
}
#OnClose
public void end() {
connections.remove(this);
String message = String.format("* %s %s", nickname, "has disconnected.");
broadcast(message);
}
#OnMessage
public void incoming(String message) {
// Never trust the client
String filteredMessage = String.format("%s: %s", nickname, message.toString());
broadcast(filteredMessage);
}
#OnError
public void onError(Throwable t) throws Throwable {
logger.error("Chat Error: " + t.toString(), t);
}
private static void broadcast(String msg) {
for (ChatAnnotation client : connections) {
try {
synchronized (client) {
client.session.getBasicRemote().sendText(msg);
}
} catch (IOException e) {
logger.debug("Chat Error: Failed to send message to client", e);
connections.remove(client);
try {
client.session.close();
} catch (IOException e1) {
// Ignore
}
String message = String.format("* %s %s", client.nickname, "has been disconnected.");
broadcast(message);
}
}
}
}
I have noting added in my web.xml. In my old project are also tcpsockets used can this be the problem?
Can anyone help me with this problem?
EDIT
Class added:
import java.util.HashSet;
import java.util.Set;
import javax.websocket.Endpoint;
import javax.websocket.server.ServerApplicationConfig;
import javax.websocket.server.ServerEndpointConfig;
import org.apache.log4j.Logger;
public class ExamplesConfig implements ServerApplicationConfig {
private static Logger log = Logger.getLogger(ChatAnnotation.class);
public Set<ServerEndpointConfig> getEndpointConfigs(Set<Class<? extends Endpoint>> endpointClasses) {
Set<ServerEndpointConfig> result = new HashSet<ServerEndpointConfig>();
log.info("getEndpointConfigs");
return result;
}
public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scanned) {
log.info("getAnnotatedEndpointClasses");
return scanned;
}
}
Java websocket server use return value of ServerApplicationConfig interface to deploy programmatic endpoints and for annotated endpoints.
For Tomcat example, if you change the package name of ChatAnnotation. You have to modify websocket.ExamplesConfig too.
public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scanned) {
// Deploy all WebSocket endpoints defined by annotations in the examples
// web application. Filter out all others to avoid issues when running
// tests on Gump
Set<Class<?>> results = new HashSet<>();
for (Class<?> clazz : scanned) {
String name = clazz.getPackage().getName();
boolean ok = name.startsWith("websocket.");
if (ok) {
results.add(clazz);
}
}
return scanned;
}
The getAnnotatedEndpointClasses(scanned) only return classes which package name start with websocket. Unmatched classes will not deployed even they have #ServerEndpoint declarations.
I have a Grizzly Http Server with Async processing added. It is queuing my requests and processing only one request at a time, despite adding async support to it.
Path HttpHandler was bound to is: "/"
Port number: 7777
Behavior observed when I hit http://localhost:7777 from two browsers simultaneously is:
Second call waits till first one is completed. I want my second http call also to work simultaneously in tandom with first http call.
EDIT Github link of my project
Here are the classes
GrizzlyMain.java
package com.grizzly;
import java.io.IOException;
import java.net.URI;
import javax.ws.rs.core.UriBuilder;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.http.server.NetworkListener;
import org.glassfish.grizzly.nio.transport.TCPNIOTransport;
import org.glassfish.grizzly.strategies.WorkerThreadIOStrategy;
import org.glassfish.grizzly.threadpool.ThreadPoolConfig;
import com.grizzly.http.IHttpHandler;
import com.grizzly.http.IHttpServerFactory;
public class GrizzlyMain {
private static HttpServer httpServer;
private static void startHttpServer(int port) throws IOException {
URI uri = getBaseURI(port);
httpServer = IHttpServerFactory.createHttpServer(uri,
new IHttpHandler(null));
TCPNIOTransport transport = getListener(httpServer).getTransport();
ThreadPoolConfig config = ThreadPoolConfig.defaultConfig()
.setPoolName("worker-thread-").setCorePoolSize(6).setMaxPoolSize(6)
.setQueueLimit(-1)/* same as default */;
transport.configureBlocking(false);
transport.setSelectorRunnersCount(3);
transport.setWorkerThreadPoolConfig(config);
transport.setIOStrategy(WorkerThreadIOStrategy.getInstance());
transport.setTcpNoDelay(true);
System.out.println("Blocking Transport(T/F): " + transport.isBlocking());
System.out.println("Num SelectorRunners: "
+ transport.getSelectorRunnersCount());
System.out.println("Num WorkerThreads: "
+ transport.getWorkerThreadPoolConfig().getCorePoolSize());
httpServer.start();
System.out.println("Server Started #" + uri.toString());
}
public static void main(String[] args) throws InterruptedException,
IOException, InstantiationException, IllegalAccessException,
ClassNotFoundException {
startHttpServer(7777);
System.out.println("Press any key to stop the server...");
System.in.read();
}
private static NetworkListener getListener(HttpServer httpServer) {
return httpServer.getListeners().iterator().next();
}
private static URI getBaseURI(int port) {
return UriBuilder.fromUri("https://0.0.0.0/").port(port).build();
}
}
HttpHandler (with async support built in)
package com.grizzly.http;
import java.io.IOException;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import javax.ws.rs.core.Application;
import org.glassfish.grizzly.http.server.HttpHandler;
import org.glassfish.grizzly.http.server.Request;
import org.glassfish.grizzly.http.server.Response;
import org.glassfish.grizzly.http.util.HttpStatus;
import org.glassfish.grizzly.threadpool.GrizzlyExecutorService;
import org.glassfish.grizzly.threadpool.ThreadPoolConfig;
import org.glassfish.jersey.server.ApplicationHandler;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.spi.Container;
import com.grizzly.Utils;
/**
* Jersey {#code Container} implementation based on Grizzly
* {#link org.glassfish.grizzly.http.server.HttpHandler}.
*
* #author Jakub Podlesak (jakub.podlesak at oracle.com)
* #author Libor Kramolis (libor.kramolis at oracle.com)
* #author Marek Potociar (marek.potociar at oracle.com)
*/
public final class IHttpHandler extends HttpHandler implements Container {
private static int reqNum = 0;
final ExecutorService executorService = GrizzlyExecutorService
.createInstance(ThreadPoolConfig.defaultConfig().copy()
.setCorePoolSize(4).setMaxPoolSize(4));
private volatile ApplicationHandler appHandler;
/**
* Create a new Grizzly HTTP container.
*
* #param application
* JAX-RS / Jersey application to be deployed on Grizzly HTTP
* container.
*/
public IHttpHandler(final Application application) {
}
#Override
public void start() {
super.start();
}
#Override
public void service(final Request request, final Response response) {
System.out.println("\nREQ_ID: " + reqNum++);
System.out.println("THREAD_ID: " + Utils.getThreadName());
response.suspend();
// Instruct Grizzly to not flush response, once we exit service(...) method
executorService.execute(new Runnable() {
#Override
public void run() {
try {
System.out.println("Executor Service Current THREAD_ID: "
+ Utils.getThreadName());
Thread.sleep(25 * 1000);
} catch (Exception e) {
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR_500);
} finally {
String content = updateResponse(response);
System.out.println("Response resumed > " + content);
response.resume();
}
}
});
}
#Override
public ApplicationHandler getApplicationHandler() {
return appHandler;
}
#Override
public void destroy() {
super.destroy();
appHandler = null;
}
// Auto-generated stuff
#Override
public ResourceConfig getConfiguration() {
return null;
}
#Override
public void reload() {
}
#Override
public void reload(ResourceConfig configuration) {
}
private String updateResponse(final Response response) {
String data = null;
try {
data = new Date().toLocaleString();
response.getWriter().write(data);
} catch (IOException e) {
data = "Unknown error from our server";
response.setStatus(500, data);
}
return data;
}
}
IHttpServerFactory.java
package com.grizzly.http;
import java.net.URI;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.http.server.NetworkListener;
import org.glassfish.grizzly.http.server.ServerConfiguration;
/**
* #author smc
*/
public class IHttpServerFactory {
private static final int DEFAULT_HTTP_PORT = 80;
public static HttpServer createHttpServer(URI uri, IHttpHandler handler) {
final String host = uri.getHost() == null ? NetworkListener.DEFAULT_NETWORK_HOST
: uri.getHost();
final int port = uri.getPort() == -1 ? DEFAULT_HTTP_PORT : uri.getPort();
final NetworkListener listener = new NetworkListener("IGrizzly", host, port);
listener.setSecure(false);
final HttpServer server = new HttpServer();
server.addListener(listener);
final ServerConfiguration config = server.getServerConfiguration();
if (handler != null) {
config.addHttpHandler(handler, uri.getPath());
}
config.setPassTraceRequest(true);
return server;
}
}
It seems the problem is the browser waiting for the first request to complete, and thus more a client-side than a server-side issue. It disappears if you test with two different browser processes, or even if you open two distinct paths (let's say localhost:7777/foo and localhost:7777/bar) in the same browser process (note: the query string partecipates in making up the path in the HTTP request line).
How I understood it
Connections in HTTP/1.1 are persistent by default, ie browsers recycle the same TCP connection over and over again to speed things up. However, this doesn't mean that all requests to the same domain will be serialized: in fact, a connection pool is allocated on a per-hostname basis (source). Unfortunately, requests with the same path are effectively enqueued (at least on Firefox and Chrome) - I guess it's a device that browsers employ to protect server resources (and thus user experience)
Real-word applications don't suffer from this because different resources are deployed to different URLs.
DISCLAIMER: I wrote this answer based on my observations and some educated guess. I think things may actually be like this, however a tool like Wireshark should be used to follow the TCP stream and definitely assert this is what happens.
I am new to Web Services with JBoss. A client is connecting to an EJB3 based Web Service
With JBoss AS 5 and JDK 6 using JAX-WS. I am stuck with the following exception:
Exception in thread "main" javax.xml.ws.WebServiceException:
Undefined port type: {http://webservice.samples/}HelloRemote
at com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:300)
at com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:306)
at javax.xml.ws.Service.getPort(Service.java:161)
at samples.client.BeanWSClient.getPort(BeanWSClient.java:44)
at samples.client.BeanWSClient.main(BeanWSClient.java:35)
BeanWSClient.java (client is a different project than EJB3 WS):
package samples.client;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import samples.webservice.HelloRemote;
public class BeanWSClient {
/**
* #param args
*/
public static void main(String[] args) throws Exception {
String endpointURI ="http://192.168.22.100:8080/SampleWSEJBProject/HelloWorld?wsdl";
String helloWorld = "Hello world!";
Object retObj = getPort(endpointURI).echo(helloWorld);
System.out.println(retObj);
}
private static HelloRemote getPort(String endpointURI) throws MalformedURLException {
QName serviceName = new QName("http://www.openuri.org/2004/04/HelloWorld", "HelloWorldService");
URL wsdlURL = new URL(endpointURI);
Service service = Service.create(wsdlURL, serviceName);
return service.getPort(HelloRemote.class);
}
HelloRemote.java:
package samples.webservice;
import javax.jws.WebService;
#WebService
//#SOAPBinding(style=SOAPBinding.Style.RPC)
public interface HelloRemote {
public String echo(String input);
}
HelloWorld.java:
package samples.webservice;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
/**
* Session Bean implementation class MyBean
*/
#WebService(name = "EndpointInterface", targetNamespace = "http://www.openuri.org/2004/04/HelloWorld", serviceName = "HelloWorldService")
#SOAPBinding(style = SOAPBinding.Style.RPC)
#Remote(HelloRemote.class)
#Stateless
public class HelloWorld implements HelloRemote {
/**
* #see Object#Object()
*/
#WebMethod
public String echo(String input) {
return input;
}
}
In HelloWorld.java, you should change the name = "EndpointInterface" parameter of the #WebService annotation to name = "HelloRemote"
OR
In BeanWSClient.java, in the getPort(String endpointURI) method, replace
return service.getPort(HelloRemote.class);
with
QName port_name = new QName("http://www.openuri.org/2004/04/HelloWorld","HelloWorldPort");
return service.getPort(port_name, HelloRemote.class);
add endpointInterface in #WebSevice annotation, if you dont mention endpoint interface give fully qualified portname while using getPort method.
try adding:
-Djava.endorsed.dirs=${jbossHome}/lib/endorsed/
as a vm argument when you execute BeanWSClient. (where jbossHome is of-course your jboss home).
the problem was, as far as i recall, jboss overwritten the sun implementation of WSService, and you need to set your class loading to load the jboss implementation before the sun's implementation.
because sun's implementation is in rt.jar you need to use endorsed lib.
Try to use this method:
//inicia classe
public void test(){
String url = "http://localhost:8080/soujava_server/HelloWorld?wsdl";
// Create an instance of HttpClient.
HttpClient client = new HttpClient();
// Create a method instance.
GetMethod method = new GetMethod(url);
// Provide custom retry handler is necessary
method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(3, false));
try {
// Execute the method.
int statusCode = client.executeMethod(method);
if (statusCode != HttpStatus.SC_OK) {
System.err.println("Method failed: " + method.getStatusLine());
}
// Read the response body.
byte[] responseBody = method.getResponseBody();
// Deal with the response.
// Use caution: ensure correct character encoding and is not binary data
System.out.println(new String(responseBody));
} catch (HttpException e) {
System.err.println("Fatal protocol violation: " + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
System.err.println("Fatal transport error: " + e.getMessage());
e.printStackTrace();
} finally {
// Release the connection.
method.releaseConnection();
}
}