javax.ws.rs.ProcessingException: URI is not absolute, while writing Mockito for a RESTFUL API - mockito

Sample Method to be Tested
#Inject
#ConfigProperty(name = "SAMPLE_WEBSERVICE_URL")
private String sampleUrl;
private boolean isStatusOK(){
Response response = client.target(sampleUrl).request().get();
response.readEntity(Object.class);
return response.getStatus() == STATUS_CODE_OK;
}
Mockito Code
#Spy
private Client client;
#Spy
private Response response;
#Test
void testIsStatusOK()() {
client = ClientBuilder.newClient();
try {
URI uri = new URI("SAMPLE_WEBSERVICE_URL");
Mockito.when(client.target(uri.relativize(uri)).request().get()).thenReturn(response);
}
catch (URISyntaxException e) {
e.printStackTrace();
}
Test case is failed because
javax.ws.rs.ProcessingException: URI is not absolute----
Caused by: java.lang.IllegalArgumentException: URI is not absolute

Related

How to add custom data on exception handling using azure webjobs SDK?

I have a simple Azure Function which returns to a queue:
private readonly TelemetryClient _telemetryClient;
[return: Queue("%ReturnQueue%")]
public async Task<string> Run([QueueTrigger("%RequestQueue%")] string msg, ILogger log)
{
try
{
//Some dependency calls
}
catch(Exception ex)
{
var dic = new Dictionary<string,string>();
dic.Add("Id", someId);
dic.Add("CustomData", cusomData);
_telemetryClient.TrackException(ex, dic);
}
}
I obviously get a compilation error saying that not all code paths returns a value.
The problem is that if I add a throw at the end of the catch block the Azure Functions runtime replicate the excpetion on the appinsights portal. How can I add custom data to my exceptions like this?
You can create your own Exception type:
public class MyCustomException : Exception
{
public string Id {get;set;}
public string CustomData {get;set;}
public Exception RootException {get;set;}
public MyCustomException(string id, string customData, Exception ex)
{
Id = id;
CustomData = customData;
RootException = ex;
}
}
private readonly TelemetryClient _telemetryClient;
[return: Queue("%ReturnQueue%")]
public async Task<string> Run([QueueTrigger("%RequestQueue%")] string msg, ILogger log)
{
try
{
//Some dependency calls
}
catch(Exception ex)
{
//var dic = new Dictionary<string,string>();
//dic.Add("Id", someId);
//dic.Add("CustomData", cusomData);
var customEx = new MyCustomException(someId, cusomData, ex);
_telemetryClient.TrackException(customEx);
}
finally
{
return "";
}
}
PS: inside MyCustomException you can actually have Dictionary rather than string properties.

Marshalling via WebServiceGatewaySupport fails with JAXBException: class <classname> nor any of its super class is known to this context

I want to call webservices via clients. The clients are instantiated as beans:
#Configuration
public class ServiceClientConfiguration {
#Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath(CONTEXT_PATH);
return marshaller;
}
#Bean
public Service1Client authenticate(Jaxb2Marshaller marshaller) {
Service1Client client = new Service1Client();
client.setDefaultUri("http://localhost:8292/service1");
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
return client;
}
#Bean
public Service2Client broker(Jaxb2Marshaller marshaller) {
Service2Client client = new Service2Client();
client.setDefaultUri("http://localhost:8192/service2");
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
return client;
}
Though the both of the services are different, the request and responses are defined via xsd-files to the same package name - which is provided here as String 'CONTEXT_PATH' to the marshaller.
The clients itself look like this:
public class Service1Client extends WebServiceGatewaySupport {
private static final Logger log = LoggerFactory.getLogger(Tools.getClassName());
public Service1Response process(Service1Request request) {
Service1Response response = null;
try {
response = (Service1Response) getWebServiceTemplate()
.marshalSendAndReceive("http://localhost:8292/service1", request);
} catch (Exception e) {
log.error("", e);
}
return response;
}
}
and
public class Service2Client extends WebServiceGatewaySupport {
private static final Logger log = LoggerFactory.getLogger(Tools.getClassName());
public Service2Response process(Service2Request request) {
Service2Response response = null;
try {
response = (Service2Response) getWebServiceTemplate()
.marshalSendAndReceive("http://localhost:8192/service2", request);
} catch (Exception e) {
log.error("", e);
}
return response;
}
}
While running Service1Client is fine, the Service2Client fails with
javax.xml.bind.JAXBException: class <package>.Service2Request nor any of its super class is known to this context.
I removed "Service1Client" from the code - but the error remained to be the same.
I have renamed the pathname of the CONTEXT_PATH. It was "types.". I changed it to "dto.". Now it works as expected.
For me the reason for the problem looks sort of strange - maybe somebody can explain it.

Mocking JestClient in SpringBoot

Springboot application is not autowiring all the instances so I manually wire all of them. Now JestClient mock is not getting set I only see the live object. Next actually I want to test if "aMethod is having jestclient.execute() then return jestResult"
#RunWith(SpringRunner.class)
#SpringBootTest(classes = IngestionApplicationTests.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#TestPropertySource(locations = "classpath:application-test.yml")
#ComponentScan(basePackages = { "com.package.accounts" })
public class IngestionApplicationTests {
#Autowired
private IngestionServiceImpl vaService;
#Autowired
private IngestionQueryUtil queryUtil;
#Mock
private JestClient client;
private JestResult result;
...
#Before
public void setUp() {
client = mock(JestClient.class);
String resultString="<jsonString>";
result.setJsonString(resultString);
result.setJsonObject(new JsonParser().parse(resultString).getAsJsonObject());
result.setSucceeded(true);
try {
when(client.execute(anyObject())).thenReturn(result);
} catch (IOException e) {
e.printStackTrace();
}
}
}
I see that Spring-Boot is creating a new context of its own and not running in test context.

Alaways goin in onFailure in retrofit2.0

I am trying to hit the api : www.xyz.com/abc_cc/cc/userregister/newuser
This is my Code :
public class MainActivity extends AppCompatActivity {
public static final String BASE_URL = "abc.com/abc_cc/cc/";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(getUnsafeOkHttpClient())
.addConverterFactory(GsonConverterFactory.create())
.build();
Endpoints endpoints= retrofit.create(Endpoints.class);
endpoints.newuser("{\"full_name\":\"sss\",\"states_id\":\"20\",\"mobile\":\"9876543210\",\"password\":\"******\",\"accept_terms\":true,\"Userid\":\"0\",\"refer\":\"\",\"ip-address\":\"1.2.3.4\",\"device_type\":\"samsung J5\",\"os-version\":\"5.0.1\",\"client\":\"app\",\"secret_key\":\"44\"}")
.enqueue(new retrofit2.Callback<Items>() {
#Override
public void onResponse(retrofit2.Call<Items> call, retrofit2.Response<Items> response) {
System.out.println("onResponse : "+response.message());
System.out.println("onResponse : "+response.body());
System.out.println("onResponse : "+response.code());
System.out.println("onResponse : "+response.errorBody());
System.out.println("onResponse : "+response.isSuccessful());
System.out.println("onResponse : "+response.raw());
System.out.println("onResponse : "+response);
}
#Override
public void onFailure(retrofit2.Call<Items> call, Throwable t) {
System.out.println("onFailure"+call);
}
});
}
public static OkHttpClient getUnsafeOkHttpClient() {
try {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
#Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] chain,
String authType) throws CertificateException {
}
#Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] chain,
String authType) throws CertificateException {
}
#Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[0];
}
} };
// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustAllCerts,
new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext
.getSocketFactory();
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient = okHttpClient.newBuilder()
.sslSocketFactory(sslSocketFactory)
.hostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER).build();
return okHttpClient;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Interface :
public interface Endpoints {
#POST("/userregister/newuser")
#FormUrlEncoded
Call<Items> newuser(#Field("Data") String Data);
}
POJO class :
public class Items {
#SerializedName("Response-Status")
#Expose
private Boolean responseStatus;
#SerializedName("Response-Validate")
#Expose
private Boolean responseValidate;
#SerializedName("Response-Message")
#Expose
private String responseMessage;
#SerializedName("Response-Data")
#Expose
private ResponseData responseData;
public Boolean getResponseStatus() {
return responseStatus;
}
public void setResponseStatus(Boolean responseStatus) {
this.responseStatus = responseStatus;
}
public Boolean getResponseValidate() {
return responseValidate;
}
public void setResponseValidate(Boolean responseValidate) {
this.responseValidate = responseValidate;
}
public String getResponseMessage() {
return responseMessage;
}
public void setResponseMessage(String responseMessage) {
this.responseMessage = responseMessage;
}
public ResponseData getResponseData() {
return responseData;
}
public void setResponseData(ResponseData responseData) {
this.responseData = responseData;
}
}
I am getting this response :
{protocol=http/1.1, code=404, message=Not Found, url=www.xyz.com/userregister/newuser}
I have given the proper url then why is it taking only half of it?
I have tried the example from https://code.tutsplus.com/tutorials/sending-data-with-retrofit-2-http-client-for-android--cms-27845. This example and the link given in the example are working fine, but if I do the same with my url then I get the above error
I Hope kindly check your parsing issues may occurred.
#Override
public void onFailure(retrofit2.Call<Items> call, Throwable t) {
System.out.println("onFailure"+call);
//add this lije you got exceptions.
t.printStackTrace();
}
Change your Endpoints interface for this:
public interface Endpoints {
#POST("userregister/newuser")
#FormUrlEncoded
Call<Items> newuser(#Field("Data") String Data);
}
Note that I removed the trailing slash /. This way Retrofit appends the path you defined to the BASE_URL.
refer to the docs for Retrofit.Builder for a more detailed explanation, but pay particular attention to these bits:
Base URLs should always end in /.
A trailing / ensures that endpoints values which are relative paths
will correctly append themselves to a base which has path components.
...
Endpoint values which contain a leading / are absolute.
Absolute values retain only the host from baseUrl and ignore any
specified path components.
as presently written, the path referenced in your call to Endpoints.newuser() is absolute, and therefore the path segments after the host in your base URL are dropped (as this is the documented behavior).
therefore, you should change your Endpoints interface to use relative paths instead, like so:
public interface Endpoints {
#POST("userregister/newuser")
#FormUrlEncoded
Call<Items> newuser(#Field("Data") String Data);
}

Spring Boot #RestController rejects a POST request

A POST request
http://localhost:9278/submitEnrollment
to a Spring Boot application that encapsulates an external SOAP call results in the following:
{
"timestamp": 1439480941381,
"status": 401,
"error": "Unauthorized",
"message": "Full authentication is required to access this resource",
"path": "/submitEnrollment"
}
This doesn't seem to be a normal behavior, I'm wondering what Spring Boot configurations I need to relax/disable to prevent this client authentication.
Here are relevant pieces of code:
Configuration for the app (that entails all the necessary plumbing to send a secured SOAP call over SSL and should affect web tier):
#Configuration
#ComponentScan({"a.b.c.d", "com.submit.enrollment"})
#PropertySource("classpath:/submit-enrollment.properties")
public class SubmitEnrollmentConfig {
#Value("${marshaller.contextPaths}")
private String[] marshallerContextPaths;
#Value("${default.Uri}")
private String defaultUri;
#Bean
public FfmSoapClient connectivityClient() throws Throwable {
FfmSoapClient client = new FfmSoapClient();
client.setWebServiceTemplate(webServiceTemplate());
return client;
}
#Bean
public KeyStore keyStore() throws Throwable {
KeyStoreFactoryBean keyStoreFactory = new KeyStoreFactoryBean();
keyStoreFactory.setPassword("!zxy!36!");
keyStoreFactory.setLocation(new ClassPathResource("zxy.jks"));
keyStoreFactory.setType("jks");
keyStoreFactory.afterPropertiesSet();
return keyStoreFactory.getObject();
}
#Bean
public KeyManager[] keyManagers() throws Throwable{
KeyManagersFactoryBean keyManagerFactory = new KeyManagersFactoryBean();
keyManagerFactory.setKeyStore(keyStore());
keyManagerFactory.setPassword("!zxy!36!");
keyManagerFactory.afterPropertiesSet();
return keyManagerFactory.getObject();
}
#Bean
public HttpsUrlConnectionMessageSender httpsUrlSender() throws Throwable {
HttpsUrlConnectionMessageSender sender = new HttpsUrlConnectionMessageSender();
sender.setSslProtocol("TLS");
sender.setKeyManagers(keyManagers());
return sender;
}
#Bean
public WebServiceTemplate webServiceTemplate() throws Throwable {
WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
webServiceTemplate.setMarshaller(marshaller());
webServiceTemplate.setUnmarshaller(marshaller());
webServiceTemplate.setDefaultUri(defaultUri);
webServiceTemplate.setMessageFactory(messageFactory());
webServiceTemplate.setMessageSender(/*new HttpComponentsMessageSender()*/httpsUrlSender());
webServiceTemplate.setInterceptors(new ClientInterceptor[] { wss4jSecurityInterceptor(), new LogbackInterceptor() }); //order matters
webServiceTemplate.setMessageSender(httpsUrlSender());
return webServiceTemplate;
}
#Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPaths(marshallerContextPaths);
return marshaller;
}
#Bean
public SaajSoapMessageFactory messageFactory() {
SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory();
messageFactory.setSoapVersion(SoapVersion.SOAP_12);
return messageFactory;
}
#Bean
public Wss4jSecurityInterceptor wss4jSecurityInterceptor() throws Throwable{
Wss4jSecurityInterceptor wss4jSecurityInterceptor = new Wss4jSecurityInterceptor();
wss4jSecurityInterceptor.setSecurementActions(/*"UsernameToken"*/WSHandlerConstants.USERNAME_TOKEN + " "+ WSHandlerConstants.TIMESTAMP);
//wss4jSecurityInterceptor.setSecurementActions("Signature");
wss4jSecurityInterceptor.setSecurementUsername("07.ZIP.NJ*.390.639");
wss4jSecurityInterceptor.setSecurementPassword("oLD#cDh$(dKnCM");
wss4jSecurityInterceptor.setSecurementPasswordType(/*"PasswordDigest"*/WSConstants.PW_DIGEST);
wss4jSecurityInterceptor.setSecurementEncryptionCrypto(crypto());
wss4jSecurityInterceptor.setSecurementEncryptionKeyIdentifier("DirectReference");
//wss4jSecurityInterceptor.setValidationActions("Signature");
//wss4jSecurityInterceptor.setValidationSignatureCrypto( crypto() );
wss4jSecurityInterceptor.setSecurementTimeToLive(300);
return wss4jSecurityInterceptor;
}
#Bean
public Crypto crypto() throws Throwable {
CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
cryptoFactoryBean.setKeyStoreLocation(new ClassPathResource("zipari.jks"));
cryptoFactoryBean.setKeyStorePassword("!zxy!36!");
cryptoFactoryBean.afterPropertiesSet();
Crypto crypto = cryptoFactoryBean.getObject();
System.out.println("created crypto store: "+ crypto);
return crypto;
}
#Configuration
static class DatabaseConfig {
#Bean #Lazy
DataSource dataSource() {
return null;
}
}
}
Application:
public static void main(String[] args) throws Throwable {
SpringApplication app = new SpringApplication(SubmitEnrollmentApplication.class);
//app.addListeners(new ApplicationPidFileWriter());
ApplicationContext ctx = app.run(args);
Controller:
#RestController
public class SubmitEnrollmentController {
private final Logger logger = LoggerFactory.getLogger(SubmitEnrollmentController.class);
//#Autowired #Qualifier("brokerService")private BrokerService service;
#RequestMapping(value = "/submitEnrollment", method = RequestMethod.POST, consumes="application/json")
public String submitEnrollment(#RequestBody String jsonIn){
logger.info("Received submit enrollment request: {}, start processing...", jsonIn);
The following addition to the main Spring config file helped me achieve what I needed:
#Configuration
static class WebSecurityConfig extends WebSecurityConfigurerAdapter{
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/**");
}
}
Your problem is, your rest endpoints are authenticated with spring security. So the error message clearly indicates that, you want to be authenticate yourself before sending the request. You can ignore the authentication, until you make sure everything is working. What you will need is something like this.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/submitEnrollment").permitAll().and().csrf().disable();
}
You can find a good config from here. If you need more complex config, go through this jhipster project, and specifically this file.
It is better you can go through these docs as well. Hope this helps.

Resources