I know that in Java a method can return only one return type... But if there is any possiblity to this, kindly let me know. From the below method I am trying to return a list if condition satisfies else i am trying to return an error message.
Here is my code:
#RequestMapping(value = "/getcompanies", method = RequestMethod.POST)
public List<CompanyMaster> getCompanies(#RequestBody UserDetails user) {
String OrgLoginId = user.getOrgLoginId();
String password = user.getuPassword();
String checkLoginId = null;
String uPassword = null;
String encPassword = null;
String loginId = null;
String checkAuthorized = null;
// String loginId=userService.getLoginId(OrgLoginId);
List<Object[]> CheckIdPassword = userService.checkLoginId(OrgLoginId);
List<Object[]> results = CheckIdPassword;
for (Object[] obj : results) {
checkLoginId = obj[0].toString();
if (null == obj[1]) {
uPassword = "";
} else {
uPassword = obj[1].toString();
}
loginId = obj[2].toString();
}
checkAuthorized = loginId.substring(0, 3);
if (null != password) {
MD5 md5 = new MD5();
encPassword = md5.getPassword(password);
}
if (checkLoginId == null) {
return "Incorrect loginId..Please enter valid loginId";
} else if (encPassword.equals(uPassword)) {
if (checkAuthorized.equals("STE")) {
List<CompanyMaster> companyList = userService.getCompanyList(OrgLoginId);
return companyList;
} else {
return "You are not Authorized";
}
} else {
return "Incorrect Password";
}
Yes its possible, create a custom Exception say 'MyAppException' and throw that exception with the error message you want.
Write your logic in a try{}catch block and throw the exception in catch so that the response has the error message
public List<CompanyMaster> getCompanies(#RequestBody UserDetails user) throws MyAppppException
{
try
{
//your logic which throws error
return companyList;
}
catch( final MyAppException we )
{
throw new MyAppException("User not found", HttpStatus.NOT_FOUND);
}
}
Refer this link
https://www.codejava.net/java-core/exception/how-to-create-custom-exceptions-in-java
You can achieve this by creating a new presenter Class which contains List and status of type String and change the return type of getCompanies method to presenter class like
public CompaniesPresenter getCompanies()
And your CompaniesPresenter class should look like
public class CompaniesPresenter {
private List<CompanyMaster> companyMaster;
private string status;
//default constructor
public CompaniesPresenter(){
}
//parameterized constructor to return only string in exception case
public CompaniesPresenter(Stirng status){
this.status = status;
}
//parametirized constructor to return success case
public CompaniesPresenter(List<CompanyMaster> companyMaster, Stirng status){
this.companyMaster = companyMaster;
this.status = status;
}
//getters and setters
}
This is how your updated method lokks like
#RequestMapping(value = "/getcompanies", method = RequestMethod.POST)
public CompaniesPresenter getCompanies(#RequestBody UserDetails user) {
String OrgLoginId = user.getOrgLoginId();
String password = user.getuPassword();
String checkLoginId = null;
String uPassword = null;
String encPassword = null;
String loginId = null;
String checkAuthorized = null;
// String loginId=userService.getLoginId(OrgLoginId);
List<Object[]> CheckIdPassword = userService.checkLoginId(OrgLoginId);
List<Object[]> results = CheckIdPassword;
for (Object[] obj : results) {
checkLoginId = obj[0].toString();
if (null == obj[1]) {
uPassword = "";
} else {
uPassword = obj[1].toString();
}
loginId = obj[2].toString();
}
checkAuthorized = loginId.substring(0, 3);
if (null != password) {
MD5 md5 = new MD5();
encPassword = md5.getPassword(password);
}
if (checkLoginId == null) {
return new CompaniesPresenter("Incorrect loginId..Please enter valid loginId");
} else if (encPassword.equals(uPassword)) {
if (checkAuthorized.equals("STE")) {
List<CompanyMaster> companyList = userService.getCompanyList(OrgLoginId);
return new CompaniesPresenter(companyList,"success");
} else {
return new CompaniesPresenter("You are not Authorized");
}
} else {
return new CompaniesPresenter("Incorrect Password");
}
This is not tested please make sure for any compilation errors
vavr's Either class would be a good choice.
The usage of custom exception is most reasonable solution. However, creating custom exception for just one case is not ideal always.
Another solution is to return empty List from your method, check if the List is empty in your servlet (or wherever you are invoking this method from), and show error message there.
It seems like you want to return multiple error messages for different cases. In this case, custom exception is recommended solution. If you don't like custom exceptions, you can return List<Object> and populate error message as the first element in the list. In the place where this List is obtained, check if the first element is instanceOf String or CompanyMaster. Based on what it is, you can perform your operations. This is a weird but possible solution (only if you don't like custom exceptions).
You need to understand the problem first. You are mixing two things here, first authorization, does the user has correct privileges to get company details, second giving the company details itself. Let's understand the first problem when a user tries to access "/getcompanies" endpoint will you let him in if does not have access, in REST world your security model should take care of it. I would use spring security to achieve this. My recommendation would be to explore on "interceptor" and solve the problem of invalid user. This will make your other problem easy as your "/getcompanies" endpoint can focus only on getting the details and return it (SRP).
I have a project that currently uses Spring Cloud Streams and RabbitMQ underneath. I've implemented a logic based on the documentation. See below:
#Component
public class ReRouteDlq {
private static final String ORIGINAL_QUEUE = "so8400in.so8400";
private static final String DLQ = ORIGINAL_QUEUE + ".dlq";
private static final String PARKING_LOT = ORIGINAL_QUEUE + ".parkingLot";
private static final String X_RETRIES_HEADER = "x-retries";
private static final String X_ORIGINAL_EXCHANGE_HEADER = RepublishMessageRecoverer.X_ORIGINAL_EXCHANGE;
private static final String X_ORIGINAL_ROUTING_KEY_HEADER = RepublishMessageRecoverer.X_ORIGINAL_ROUTING_KEY;
#Autowired
private RabbitTemplate rabbitTemplate;
#RabbitListener(queues = DLQ)
public void rePublish(Message failedMessage) {
Map<String, Object> headers = failedMessage.getMessageProperties().getHeaders();
Integer retriesHeader = (Integer) headers.get(X_RETRIES_HEADER);
if (retriesHeader == null) {
retriesHeader = Integer.valueOf(0);
}
if (retriesHeader < 3) {
headers.put(X_RETRIES_HEADER, retriesHeader + 1);
String exchange = (String) headers.get(X_ORIGINAL_EXCHANGE_HEADER);
String originalRoutingKey = (String) headers.get(X_ORIGINAL_ROUTING_KEY_HEADER);
this.rabbitTemplate.send(exchange, originalRoutingKey, failedMessage);
}
else {
this.rabbitTemplate.send(PARKING_LOT, failedMessage);
}
}
#Bean
public Queue parkingLot() {
return new Queue(PARKING_LOT);
}
}
It does what it is expected, however, it is binded to RabbitMQ, and my company is planning to stop using this message broker in one year or two (don't know why, must be some crazy business). So, I want to implement the same thing, but detach it from any message broker.
I tried changing the rePublish method this way, but it does not work:
#StreamListener(Sync.DLQ)
public void rePublish(Message failedMessage) {
Map<String, Object> headers = failedMessage.getHeaders();
Integer retriesHeader = (Integer) headers.get(X_RETRIES_HEADER);
if (retriesHeader == null) {
retriesHeader = Integer.valueOf(0);
}
if (retriesHeader < 3) {
headers.put(X_RETRIES_HEADER, retriesHeader + 1);
String exchange = (String) headers.get(X_ORIGINAL_EXCHANGE_HEADER);
String originalRoutingKey = (String) headers.get(X_ORIGINAL_ROUTING_KEY_HEADER);
this.rabbitTemplate.send(exchange, originalRoutingKey, failedMessage);
}
else {
this.rabbitTemplate.send(PARKING_LOT, failedMessage);
}
}
It fails because the Message class has immutable Headers - throws exception on the put attempt saying you can't change its values (uses org.springframework.messaging.Message class).
Is there a way to implement this dead-letter queue handler in a message broker independent way?
Use
MessageBuilder.fromMessage(message)
.setHeader("foo", "bar")
...
.build();
Note that the message in #StreamListener is a spring-messaging Message<?>, not a spring-amqp Message and can't be sent using the template that way; you need an output binding to send the message to.
I have a .NET WebService that I'd like to access through a WinForms and a Java application.
As of now I only get the datagridview filled rows and columns contaning probably the length of the string(?). And I haven't found a way for Java to interpret the List
I would like to be able to fill rows and columns in both the JTable in Java as well as the datagridview in WinForms/C#. Therefore I wonder if perhaps a 2d-string array is better, since I will be able to define both columns and rows?
This is the asmx web-service c# class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
namespace WS_ERP
{
/// <summary>
/// Summary description for ERPService
/// </summary>
[WebService(Namespace = "http://erpimlement.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class ERPService : System.Web.Services.WebService
{
private DAL dal = new DAL();
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
[WebMethod]
public List<List<string>> Fill(string s)
{
return dal.ShowData(s);
}
[WebMethod]
public List<string> GetEmpTbl()
{
return null;
}
[WebMethod]
public List<List<string>> ShowAbsData() {
return dal.GetEmpAbsData();
}
}
}
The SQL is accessed through my DAL, see below:
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
namespace WS_ERP
{
public class DAL
{
SqlConnection con = new SqlConnection();
public DAL()
{
con.ConnectionString =
"user id=cronus;" +
"password=cronus;server=DESKTOP-LAMR8JS;" +
"Trusted_Connection=yes;" +
"database=Demo Database NAV (5-0); " +
"connection timeout=30";
}
//---------------------- SHOW DATA METHOD ----------------------//
public List<List<string>> ShowData(string s)
{
con.Open();
string query = s;
SqlCommand cmd = new SqlCommand(query,con);
SqlDataReader result = cmd.ExecuteReader();
if (result != null)
{
List<List<string>> list = new List<List<string>>();
while (result.Read())
{
List<string> tmp = new List<string>();
for (int i = 0; i < result.FieldCount; i++)
{
string data = "";
if(result.GetFieldType(i) == typeof(string))
{
data = (string)result.GetString(i);
}
if(result.GetFieldType(i) == typeof(int))
{
int integer = result.GetInt32(i);
data = integer.ToString();
}
tmp.Add(data);
}
list.Add(tmp);
}
return list;
}
return null;
}
Method invoked from application
public List<List<string>> GetEmpAbsData() {
string s = "SELECT * from [CRONUS Sverige AB$Employee Absence] WHERE [From Date] LIKE '%2004%' AND [Cause of Absence Code] = 'SJUK'";
return ShowData(s);
}
Below is the source code for the form.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ERPForm.ServiceReference1;
namespace ERPForm
{
public partial class Form1 : Form
{
ERPServiceSoapClient client = new ERPServiceSoapClient();
public Form1()
{
InitializeComponent();
comboBox1.DataSource = client.GetEmpTbl();
}
private void btnShow_Click(object sender, EventArgs e)
{
foreach(List<string> list in client.ShowAbsData() ){
for (int i = 0; i < list.Count; i++)
{
string s = list[i] + "\n";
richTextBox1.Text += s;
}
}
}
}
As of now I only get the datagridview filled rows and columns contaning probably the length of the string(?). And I haven't found a way for Java to interpret the List
I would like to be able to fill rows and columns in both the JTable in Java as well as the datagridview in WinForms/C#. Therefore I wonder if perhaps a 2d-string array is better, since I will be able to define both columns and rows?
It's a quite specific question but after days stuck in the same place and not getting any response in the Alljoyn forum, I decided to post it here. Maybe someone worked with this framework.
I am doing a project and I need the use of the signal mechanish that Alljoyn framework provides. However, I do need the signals inside a session and the example provides in the api core is sessionless.
In my case I need the service (server) to raise a signal and the client to receive it, but I am getting this error. Following the api samples, I managed to create a simple app that exchange messages through the methods defined in the interface, so I know that the communication is working. In this case, the service waits until the client connects and the send the signal. The client joins the session and right after register the signal and I am getting the BUS_NO_SUCH_INTERFACE error. I tried also to register after and before sending the signal, same problem. I think that for some reason the client does not find the bussignalhandler but I don't know why. I also put it in an external class and it didn't work.
I'm following the example in the core api guide:
https://allseenalliance.org/developers/develop/api-guide/core/android
This is the part where the service register and emit the signal:
SignalEmitter emitter = new SignalEmitter(mySignalInterface, joinerName,
sessionId,
SignalEmitter.GlobalBroadcast.Off);
myInterface = emitter.getInterface(SampleInterface.class);
// Emitting signals myInterface.buttonClicked(1);
myInterface.playerPosition(12, 1, -24);
However, in that example, I can't see a definition for myInterface. and I know it is not a mistake and they meant mySignalInterface because the method getInterface asks for an interface object and mySignalInterface is a class which implements that interface.
I put here the example I created and I'll upload the files in case someone wants to try them.
#BusInterface(name = "org.alljoyn.bus.samples.simple.SimpleInterface")
public interface SimpleInterface {
#BusMethod
String Ping(String inStr) throws BusException;
#BusSignal
public void playerPosition(int x, int y, int z) throws BusException;
}
Service:
Class inside the service to implement the signal and method
class SimpleService implements SimpleInterface, BusObject {
public String Ping(String inStr) {
mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_PING, inStr));
return inStr;
}
public void playerPosition(int x, int y, int z) { /* no implementation needed here*/}
}
Here part of the code that makes the connection in the service:
case CONNECT: {
org.alljoyn.bus.alljoyn.DaemonInit.PrepareDaemon(getApplicationContext());
mBus = new BusAttachment(getPackageName(), BusAttachment.RemoteMessage.Receive);
mBus.registerBusListener(new BusListener());
Status status = mBus.registerBusObject(mSimpleService, "/SimpleService");
if (status != Status.OK) {...}
status = mBus.connect();
logStatus("BusAttachment.connect()", status);
if (status != Status.OK) {...}
int flag = 0;
status = mBus.requestName(SERVICE_NAME, flag);
logStatus(String.format("BusAttachment.requestName(%s, 0x%08x)", SERVICE_NAME, flag), status);
if (status == Status.OK) {
status = mBus.advertiseName(SERVICE_NAME, SessionOpts.TRANSPORT_ANY);
logStatus(String.format("BusAttachement.advertiseName(%s)", SERVICE_NAME), status);
if (status != Status.OK) {...}
}
Mutable.ShortValue contactPort = new Mutable.ShortValue(CONTACT_PORT);
SessionOpts sessionOpts = new SessionOpts();
sessionOpts.traffic = SessionOpts.TRAFFIC_MESSAGES;
sessionOpts.isMultipoint = false;
sessionOpts.proximity = SessionOpts.PROXIMITY_ANY;
sessionOpts.transports = SessionOpts.TRANSPORT_ANY + SessionOpts.TRANSPORT_WFD;
status = mBus.bindSessionPort(contactPort, sessionOpts, new SessionPortListener() {
#Override
public boolean acceptSessionJoiner(short sessionPort, String joiner, SessionOpts sessionOpts) {
return sessionPort == CONTACT_PORT;
}
#Override
public void sessionJoined(short port, int id, String s) {
sessionId = id; joinerName = s; sessionEstablished = true;
}
});
logStatus(String.format("BusAttachment.bindSessionPort(%d, %s)",
contactPort.value, sessionOpts.toString()), status);
if (status != Status.OK) {...}
try {
while (!sessionEstablished) {
Thread.sleep(10);
}
SignalEmitter emitter = new SignalEmitter(mSimpleService, joinerName, sessionId, SignalEmitter.GlobalBroadcast.Off);
SimpleInterface myInterface = emitter.getInterface(SimpleInterface.class);
myInterface.playerPosition(12,1,1);
}
catch (BusException ex) {... }
}
Client:
/*On create of the activity which has a button and a text view to send text to the server */
mEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_NULL
&& event.getAction() == KeyEvent.ACTION_UP) {
/* Call the remote object's Ping method. */
Message msg = mBusHandler.obtainMessage(BusHandler.PING,
view.getText().toString());
mBusHandler.sendMessage(msg);
}
return true;
}
});
private static final String SERVICE_NAME = "org.alljoyn.bus.samples.simple";
private static final short CONTACT_PORT=42;
private BusAttachment mBus;
private ProxyBusObject mProxyObj;
private SimpleInterface mSimpleInterface;
case CONNECT: {
org.alljoyn.bus.alljoyn.DaemonInit.PrepareDaemon(getApplicationContext());
mBus = new BusAttachment(getPackageName(), BusAttachment.RemoteMessage.Receive);
mBus.registerBusListener(new BusListener() {
#Override
public void foundAdvertisedName(String name, short transport, String namePrefix) {
if(!mIsConnected) {
Message msg = obtainMessage(JOIN_SESSION);
msg.arg1 = transport;
msg.obj = name;
sendMessage(msg);
}
}
});
Status status = mBus.connect();
logStatus("BusAttachment.connect()", status);
if (Status.OK != status) {...}
status = mBus.findAdvertisedName(SERVICE_NAME);
logStatus(String.format("BusAttachement.findAdvertisedName(%s)", SERVICE_NAME), status);
if (Status.OK != status) {...}
break;
}
case (JOIN_SESSION): {
if (mIsStoppingDiscovery) {
break;
}
short contactPort = CONTACT_PORT;
SessionOpts sessionOpts = new SessionOpts();
sessionOpts.transports = (short)msg.arg1;
Mutable.IntegerValue sessionId = new Mutable.IntegerValue();
Status status = mBus.joinSession((String) msg.obj, contactPort, sessionId, sessionOpts, new SessionListener() {
#Override
public void sessionLost(int sessionId, int reason) {
mIsConnected = false;
logInfo(String.format("MyBusListener.sessionLost(sessionId = %d, reason = %d)", sessionId,reason));
mHandler.sendEmptyMessage(MESSAGE_START_PROGRESS_DIALOG);
}
});
if (status == Status.OK) {
mProxyObj = mBus.getProxyBusObject(SERVICE_NAME,
"/SimpleService",
sessionId.value,
new Class<?>[] { SimpleInterface.class });
mSimpleInterface = mProxyObj.getInterface(SimpleInterface.class);
mSessionId = sessionId.value;
mIsConnected = true;
mHandler.sendEmptyMessage(MESSAGE_STOP_PROGRESS_DIALOG);
}
break;
status = mBus.registerSignalHandlers(this);
if (status != Status.OK) {...}
}
case PING: {
try {
if (mSimpleInterface != null) {
sendUiMessage(MESSAGE_PING, msg.obj);
String reply = mSimpleInterface.Ping((String) msg.obj);
sendUiMessage(MESSAGE_PING_REPLY, reply);
} catch {...}
}
...here some more code...
#BusSignalHandler(iface="org.alljoyn.bus.samples.simple.SimpleInterface", signal="playerPosition")
public void playerPosition(int x, int y, int z) {
sendUiMessage(MESSAGE_POST_TOAST, "Signal captured");
}
In this example, I have my client which has a textview where I can add text and send a ping to the server. This is working if I get rid of the registering signal part. I tried to do it as the api core says, with the Thread.sleep but doesn't work either.
Here I add the code of both of my applications (client & server) based on the samples that are in the alljoyn api.
https://github.com/JavierT/Alljoyn_signal_sample
Please let me know if you have some doubts, it was hard to put all the information in one post.
Thank you in advance.
I think this should solve your problem
Alljoyn BusSignalHandler
either of the following may be used to annotate a signal handler:
#BusSignalHandler(iface = "org.sample.MyInterface", signal = "MySignal")
public void handleSignal(String str)
{
}
#BusSignalHandler(iface = "org.myapp.IMyInterface", signal = "EmitMySignal")
public void handleSignal(String str)
{
}
The first example may be used succesfully when IMyInterface is known to the BusAttachment via a previous call to BusAttachment.registerBusObject(BusObject, String) or BusAttachment.getProxyBusObject(String, String, int, Class[]).
The second example may be used succesfully when IMyInterface is unknown to the BusAttachment.
using the second example should solve your problem.
Also, in your Client program as per the link provided above,
#BusSignalHandler(iface="org.alljoyn.bus.samples.simple.SimpleInterface", signal="playerPosition")
should be replaced with
#BusSignalHandler(iface="org.alljoyn.bus.samples.simpleclient.SimpleInterface", signal="playerPosition")
When you call registerSignalHandlers you must pass an object that implements the interface SimpleInterface and the method playerPosition will be called in that object when you receives a signal.
I believe (I've read the code quickly, I hope I'm not wrong) that you pass your BusHandler object, which does not implements SimpleInterface.
Please change :
private static final String SERVICE_NAME = "org.alljoyn.bus.samples.simple";
to
"org.alljoyn.bus.samples.simple.SimpleInterface" as you have interface name ,
both should be same . as when the Get method of BusObject is called the interface names does not match.
Currently, I want to return the return xml result with XML with the below format :
I tried to use something like this
#XmlRootElement(name = "item")
public class Book implements Serializable {
#XmlAttribute
public int getBookId() {
return bookId;
}
...
....
and
#XmlRootElement(name = "OneBoxResults")
public class JavaClazz {
private List<Book> OneBoxResults;
public List<Book> getOneBoxResults() {
return OneBoxResults;
}
#XmlElements(#XmlElement(name = "book", type = Book.class))
public void setOneBoxResults(List<Book> oneBoxResults) {
OneBoxResults = oneBoxResults;
}
...
However, the return result which I received is only Json format as below :
{"oneBoxResults":[{"bookId":1,"bookName":"Search
Deployment","update":"2014-01-07","description":"A successful deployment
typically involves the following
elements:","path":null},{"bookId":2,"bookName":"GSA
Information","update":"2015-01-07","description":"Configure the OneBox
module so it sends search queries to the provider (a custom
application","path":null}]}
I also attemped to create new format in controller as below :
#RequestMapping(value = "/rest.oneboxSample",produces = MediaType.APPLICATION_XML_VALUE, method = RequestMethod.GET)
public #ResponseBody String oneboxSample(){
String tmpOpenField = "<Field name=\"";
String tmpCloseField = "</Field>";
StringBuilder builder = new StringBuilder();
builder.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
builder.append("<OneBoxResults>").append("<resultCode>");
builder.append("Listbook").append("<resultCode>");
for(int i = 0; i < bookDao.getBooks().size(); i++){
Book tmpBook = bookDao.getBooks().get(i);
builder.append("<MODULE_RESULT>");
builder.append(tmpOpenField).append("bookId\">").append(tmpBook.getBookId()).append(tmpCloseField);
builder.append(tmpOpenField).append("bookName\">").append(tmpBook.getBookName()).append(tmpCloseField);
builder.append(tmpOpenField).append("update\">").append(tmpBook.getUpdate()).append(tmpCloseField);
builder.append(tmpOpenField).append("description\">").append(tmpBook.getDescription()).append(tmpCloseField);
builder.append(tmpOpenField).append("path\">").append(tmpBook.getPath()).append(tmpCloseField);
builder.append("</MODULE_RESULT>");
}
builder.append("</OneBoxResults>");
return builder.toString();
}
But the result is not good. It returned a string instead of xml format which we need.
Now, our system need to receive a xml format instead of an original xml format.
Please tell me know the way to do it .
The below is my source code which I wrote
https://www.dropbox.com/s/4tyg0kp7gkzodod/onebox-service.zip?dl=0
Thanks,