wsgen exposes methods that are not annotated with #WebMethod - java

I have the following minimal webservice defined:
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
#WebService
public class DummyWS {
public static void main(String[] args) {
final String url= "http://localhost:8888/Dummy";
final Endpoint endpoint= Endpoint.create(new DummyWS());
endpoint.publish(url);
}
#WebMethod
public void putData(final String value) {
System.out.println("value: "+value);
}
#WebMethod
public void doSomething() {
System.out.println("doing nothing");
}
public void myInternalMethod() {
System.out.println("should not be exposed via WSDL");
}
}
As you can see I have two methods I want to expose, since they are annotated with #WebMethod: putData and doSomething.
But when running wsgen, it generates a WSDL that contains the myInternalMethod although it is not annotated.
Do I have a misconfiguration here? Why is a method exposed that is not annotated with #WebMethod?

OK, I found it. Per default all public methods are exposed. To exclude a method one must annotate it with #WebMethod(exclude=true).
This is quite a strange requirement, because it means that I only have to annotate those methods with #WebMethod that I do not want to expose.
This is the correct code then:
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
#WebService
public class DummyWS {
public static void main(String[] args) {
final String url= "http://localhost:8888/Dummy";
final Endpoint endpoint= Endpoint.create(new DummyWS());
endpoint.publish(url);
}
public void putData(final String value) {
System.out.println("value: "+value);
}
public void doSomething() {
System.out.println("doing nothing");
}
#WebMethod(exclude=true)
public void myInternalMethod() {
System.out.println("should not be exposed via WSDL");
}
}

Related

How could I use abstract class on spring framework?

I'm the one leaning how to write a code using Spring Boot. Then when I tried to write a code that used abstract class, I got an error as below.
Description:
Parameter 0 of constructor in com.in28minutes.spring.practice.springmasterclasspractice.devicefactory.LaptopManufacturingProcess required a bean of type 'java.lang.String' that could not be found.
Action:
Consider defining a bean of type 'java.lang.String' in your configuration.
Could you guys give me an advise how I could solve the error?
Spring Boot: v2.1.4
Java: 10.0.2
Maven: 3.6.0
SpringMasterClassPracticeDeviceFactoryApplication class
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
#SpringBootApplication
public class SpringMasterClassPracticeDeviceFactoryApplication {
private static Logger LOGGER = LoggerFactory.getLogger(SpringMasterClassPracticeDeviceFactoryApplication.class);
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication
.run(SpringMasterClassPracticeDeviceFactoryApplication.class, args);
ManufacturingImpl manufacturingImpl = applicationContext.getBean(ManufacturingImpl.class);
System.out.println(manufacturingImpl);
// manufacturingImpl.manifactureProduct("Laptop Process");
LOGGER.info("{}", manufacturingImpl);
}
}
ManufacturingImpl class
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
#Component
public class ManufacturingImpl {
#Autowired
#Qualifier("laptop")
private GeneralManufacturingProcess generalManufacturingProcess;
public void manifactureProduct(String processName) {
System.out.println(generalManufacturingProcess);
generalManufacturingProcess.launchProcess();
}
}
GeneralManufacturingProcess class
public abstract class GeneralManufacturingProcess {
private String processName;
public GeneralManufacturingProcess(String processName) {
this.processName = processName;
}
public String getProcessName() {
return processName;
}
public void launchProcess() {
if (processName != null && !processName.isEmpty()) {
assembleDevice();
testDevice();
packageDevice();
storeDevice();
} else {
System.out.println("No process name was specified");
}
}
protected abstract void assembleDevice();
protected abstract void testDevice();
protected abstract void packageDevice();
protected abstract void storeDevice();
}
LaptopManufacturingProcess class
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
#Component
#Qualifier("laptop")
public class LaptopManufacturingProcess extends GeneralManufacturingProcess {
public LaptopManufacturingProcess(String processName) {
super(processName);
}
#Override
protected void assembleDevice() {
System.out.println("Assembled laptop: " + getProcessName());
}
#Override
protected void testDevice() {
System.out.println("Tested laptop: " + getProcessName());
}
#Override
protected void packageDevice() {
System.out.println("Packaged laptop: " + getProcessName());
}
#Override
protected void storeDevice() {
System.out.println("Stored laptop: " + getProcessName());
}
}
There are Multiple ways to solve this. The problem is, that the Spring Framework is trying to create an instance of LaptopManufacturingProcess with the single constructor, which accepts a String. So the Framework is trying to autowire a Bean of type String into the constructor, which simply does not work.
Basically, what you can do is the following:
create a no-args constructor, and have it pass a hardcoded string to the parent constructor:
public LaptopManufacturingProcess() {
super("String");
}
Add an #Value-Annotation to read the String from a PropertySource:
public LaptopManufacturingProcess(#Value("${property.key.here}") String processName) {
super(processName);
}
Create a Factory Bean to create instances of GeneralManufacturingProcess on demand

How to make jUnit class have parameter

I have problem with passing a bean class like mvc concept to implement to jUnit class. I don't want change the structure jUnit class, because i have need it.
Class DataBean
public class DataBean {
private String browserName;
private String userName;
public String getBrowserName() {
return browserName;
}
public void setBrowserName(String browserName) {
this.browserName = browserName;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
Class Main
public class Main {
public static void main(String[] args) {
String[] arrBrowserName = {"chrome", "firefox"};
String[] arrUserName = {"user1", "user2"};
for(int i=0; i<2; i++) {
DataBean dataBean = new DataBean();
String browserName = arrBrowserName[i];
String userName = arrUserName[i];
dataBean.setBrowserName(browserName);
dataBean.setUserName(userName);
//How to call "TestCase1", include passing the "databean"
JUnitCore junit = new JUnitCore();
junit.run(TestCase1.class);
}
}
}
Class TestCase1
public class TestCase1 {
DataBean dataBean = new DataBean();
//Here, how to do ? i want to get "databean" from "Main" class, without change this is class as jUnit
#Before
public void setUp(){
//set up based on data from "Main class"
}
#Test
public void scenario(){
//
}
#After
public void tearDown(){
//
}
}
Based on the above code, let's say i have 2 data as data testing, i want setup the before based on the data from Main class. Where is i placement the parameter in TestCase1 so that I can get databean ? and is this possible?
FYI, the DataBean object is a smell called anemic object.
It is a DTO (object to transport data), so except when required by some framework, try to keep these immutable, or at least make it explicit that there is no encapsulation:
public class DataBean {
public String browserName;
public String userName;
}
Anyway, it seems that you are trying to parameterize a test.
Given that the test object is built by JUnit, you will have to change the test class using the API provided by JUnit to inject the needed object/data.
You could use a ThreadLocal storage to bypass the framework API, but I do not recommand it at all.
If you use JUnit, do it the JUnit way.
Assuming that you still use JUnit4, you can go (at least) two ways:
First, using JUnit4 built-in runner Parameterized, making a test class parameterized:
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
#RunWith(Parameterized.class)
public class BrowserTest {
#Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
{new DataBean("chrome", "user1")},
{new DataBean("firefox", "user2")}
});
}
private final DataBean dataBean;
public BrowserTest(DataBean dataBean) {
this.dataBean = dataBean;
}
#Test
public void test() {
// Test using a dataBean instance
}
}
Second, use a third library called JUnitParams with the runner JUnitParamsRunner, making a test method parameterized:
import org.junit.Test;
import org.junit.runner.RunWith;
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
#RunWith(JUnitParamsRunner.class)
public class BrowserTest {
#Test
#Parameters(method = "test_cases")
public void test(DataBean dataBean) {
// Test using a dataBean instance
}
public static Object[] test_cases() {
return new Object[]{
new DataBean("chrome", "user1"),
new DataBean("firefox", "user2")
};
}
}
Finally, there is the new version, JUnit5 which changes a lot regarding its extention model as it allows composition of features (instead of having only one runner).
With JUnit5, the same test can be written like this:
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
class BrowserTest {
#ParameterizedTest
#CsvSource({
"chrome, user1",
"firefox, user2"
})
void test(String browserName, String userName) {
// Test using a dataBean instance
}
}
Hope this helps !

Registering a custom ValueParamProvider in Jersey 2.27

I realize that these are internal APIs, but if they're available internally why not make them usable by the less privileged masses, and they're also extremely useful. Even though these APIs were internal in Jersey 2.25 they could be used, and I'd like to upgrade my Jersey version without breaking my custom Jersey extensions.
It's certainly possible to extend ValueParamProvider in Jersey 2.27, but I no longer see a way to register that Provider along with it's triggering annotation. Looking at how Jersey does this for its own implementations, it now uses a BoostrapConfigurator, which seems to be internalized to such an extent that external implementations can't use the same methodology.
Maybe I'm wrong about that, and if someone has a clear description of how, that would be great. Otherwise, does anyone know of a method for doing the same thing?
This used to work...
ResourceConfig resourcceConfig = ...
resourceConfig.register(new AbstractBinder() {
#Override
protected void configure (){
bind(MyParamValueFactoryProvider.class).to(ValueFactoryProvider.class).in(Singleton.class);
bind(MyParamInjectionResolver.class).to(new TypeLiteral<InjectionResolver<EntityParam>>() {
}).in(Singleton.class);
}
}
});
With appropriate implementations of AbstractValueFactoryProvider and ParamInjectionResolver.
Now it looks like you need to implement ValueParamProvider, which is easy enough, but I'm not sure how to register that properly with the Jersey framework anymore. Any help appreciated.
You don't need to use any BootstrapConfigurator. All you need to is add the services to the injector and they will be added later to the list of value providers.
To configure it, you can still use the AbstractBinder, but instead of the HK2 one, use the Jersey one. The ValueParamProvider can still be bound the same way, but for the InjectionResolver, you should make sure to implement not the HK2 resolver, but the Jersey one. Then instead of binding to TypeLiteral, bind to GenericType.
I just want to add that a misconception that people have when trying to implement parameter injection is that we also need an InjectResolver to use a custom annotation for the method parameter. This is not the case. The method parameter annotation is just a marker annotation that we should check inside ValueParamProvider#getValueProvider() method. An InjectResolver is only needed for non-method-parameter injections, for instance field and constructor injection. If you don't need that, then you don't need the InjectionResolver.
Below is a complete example using Jersey Test Framework. I didn't use an InjectionResolver, just to show that it's not needed.
import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.server.ContainerRequest;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.model.Parameter;
import org.glassfish.jersey.server.spi.internal.ValueParamProvider;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.core.Response;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.function.Function;
import static org.assertj.core.api.Assertions.assertThat;
public class ParamInjectTest extends JerseyTest {
#Target({ElementType.PARAMETER, ElementType.FIELD})
#Retention(RetentionPolicy.RUNTIME)
public #interface Auth {
}
private static class User {
private String username;
public User(String username) {
this.username = username;
}
public String getUsername() {
return this.username;
}
}
public static class AuthValueParamProvider implements ValueParamProvider {
#Override
public Function<ContainerRequest, ?> getValueProvider(Parameter parameter) {
if (parameter.getRawType().equals(User.class)
&& parameter.isAnnotationPresent(Auth.class)) {
return new UserParamProvider();
}
return null;
}
private class UserParamProvider implements Function<ContainerRequest, User> {
#Override
public User apply(ContainerRequest containerRequest) {
return new User("Peeskillet");
}
}
#Override
public PriorityType getPriority() {
return Priority.HIGH;
}
}
public static class AuthFeature implements Feature {
#Override
public boolean configure(FeatureContext context) {
context.register(new AbstractBinder() {
#Override
protected void configure() {
bind(AuthValueParamProvider.class)
.to(ValueParamProvider.class)
.in(Singleton.class);
}
});
return true;
}
}
#Path("test")
#Consumes("text/plain")
public static class TestResource {
#POST
#Produces("text/plain")
public Response post(String text, #Auth User user) {
return Response.ok(user.getUsername() + ":" + text).build();
}
}
#Override
public ResourceConfig configure() {
return new ResourceConfig()
.register(TestResource.class)
.register(AuthFeature.class);
}
#Test
public void testIt() {
final Response response = target("test")
.request()
.post(Entity.text("Test"));
assertThat(response.getStatus()).isEqualTo(200);
assertThat(response.readEntity(String.class)).isEqualTo("Peeskillet:Test");
}
}
Another thing I'll mention is that in previous versions where you extended AbstractValueFactoryProvider and implemented a ParamInjectionResolver, most people did this to follow how Jersey implemented parameter injection while still allowing for other injection points (field and constructor). If you still want to use this pattern, you can.
Below is the AuthFeature from the above test refactored
public static class AuthFeature implements Feature {
#Override
public boolean configure(FeatureContext context) {
InjectionManager im = InjectionManagerProvider.getInjectionManager(context);
AuthValueParamProvider authProvider = new AuthValueParamProvider();
im.register(Bindings.service(authProvider).to(ValueParamProvider.class));
Provider<ContainerRequest> request = () -> {
RequestProcessingContextReference reference = im.getInstance(RequestProcessingContextReference.class);
return reference.get().request();
};
im.register(Bindings.injectionResolver(new ParamInjectionResolver<>(authProvider, Auth.class, request)));
return true;
}
}
I figured this stuff out just digging through the source. All this configuration I saw in the ValueParamProviderConfigurator. You don't need to implement your own ParamInjectionResolver. Jersey has a concrete class already that we can just use, as done in the feature above.
If you change the TestResource to inject by field, it should work now
#Path("test")
#Consumes("text/plain")
public static class TestResource {
#Auth User user;
#POST
#Produces("text/plain")
public Response post(String text) {
return Response.ok(user.getUsername() + ":" + text).build();
}
}

#Inject delivers null in Weld 3 using Java SE

I am using CDI 2.0 with Weld 3.0.0 final (complete weld-se-shaded.jar in the classpath) in a plain Java SE 8 program, as shown below. What is wrong with it or am I missing something, since #Inject does nothing, i.e., the references stay null? Programmatic access as illustrated works.
I thought to post this into JBoss/Weld Jira Bug tracking system. However, after registration and login, I cannot find the button to create a new entry.
Thanks for your help,
StartUp.java
import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.se.SeContainerInitializer;
public class StartUp {
public static void main(String[] args) {
// start CDI Container
SeContainerInitializer initializer = SeContainerInitializer.newInstance();
try (SeContainer container = initializer.initialize()) {
Test t = new Test();
// start tests
t.test(container);
}
}
}
Test.java
import javax.enterprise.event.Event;
import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.spi.CDI;
import javax.inject.Inject;
public class Test {
#Inject
// IMyBean myBean; // does not work
MyBean myBean; // does not work
#Inject
Event<UserEvent> event; // does not work
public void test(SeContainer container) {
myBean.greete("World"); // NullPointerException
// manual lookup
// MyBean myBean2 = container.select(MyBean.class).get();
IMyBean myBean2 = CDI.current().select(IMyBean.class).get();
myBean2.greete("World");
event.fire(new UserEvent("info")); // NullPointerException
}
}
MyBean.java
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Named;
#Named
#ApplicationScoped
public class MyBean implements IMyBean {
public void greete(String s) {
System.out.println("Hello, " + s + "!");
}
}
SyncEventObserver.java
import javax.enterprise.event.Observes;
public class SyncEventObserver {
public void observeUserEvent(#Observes UserEvent userEvent) {
System.out.println("Received event:" + userEvent.getMessage());
}
}
UserEvent.java
public class UserEvent {
private String message;
public UserEvent() {
}
public UserEvent(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
META-INF/beans.xml
<beans version="2.0" bean-discovery-mode="all"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd">
</beans>
IMyBean.java
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Named;
#Named
#ApplicationScoped
public interface IMyBean {
void greete(String s);
}
Your main method should look like this
public static void main(String[] args) {
// start CDI Container
SeContainerInitializer initializer = SeContainerInitializer.newInstance();
try (SeContainer container = initializer.initialize()) {
Test t = container.select(Test.class).get();
// start tests
t.test(container);
}
}
The reason being - you have injection points in your test class, but you instantiate it. That removes CDI from managing your beans.

Guice dependency injector Null pointer exception

I am used the following code in java.I don't know what I did Wrong here.
My main file is:look and check
package com.sample.test;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class mymain {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new AppInjectory());
ApplicationExample obj = injector.getInstance(ApplicationExample.class);
obj.sendMessage();
}
}
My interface is:look and check
package com.sample.test;
public interface MessageService {
boolean sendMessage(String msg, String receipient);
}
My config file is look and check
package com.sample.test;
import com.google.inject.AbstractModule;
public class AppInjectory extends AbstractModule {
#Override
protected void configure() {
bind(MessageService.class).to(EmailService.class);
}
}
my application file is:look and check
package com.sample.test;
import javax.inject.Inject;
public class ApplicationExample {
private MessageService service;
#Inject
public void setService(MessageService svc){
this.service=svc;
}
public void sendMessage() {
System.out.println(“I am here”);
service.sendMessage(“welcome”, “java”);
}
}
my service class is :look and check
package com.sample.test;
//import com.google.inject.Singleton;
import javax.inject.Singleton;
#Singleton
public class EmailService implements MessageService {
public boolean sendMessage(String msg, String receipient) {
//some fancy code to send email
System.out.println(“Email Message sent to “+receipient+” with message=”+msg);
return true;
}
}
Here I am getting NUll pointer exception .What wrong I did here.?please help to fix this issue.I added the error stack trace here.
please look at it.
ERROR:
Exception in thread “main” I am here
java.lang.NullPointerException
at com.sample.test.ApplicationExample.sendMessage(ApplicationExample.java:16)
at com.sample.test.mymain.main(mymain.java:13)
The problem lies in this line:
ApplicationExample obj = injector.getInstance(ApplicationExample.class);
In your AppInjectory module you haven't bound your ApplicationExample interface to an implementation. Did you perhaps mean to do this (deducted from your module):
MessageService obj = injector.getInstance(MessageService.class);

Categories

Resources