in Opentelemetry, not able to get parent span - java

I am new to OpenTelemetry word. I have created spans for my services separately, but when i am try to combine spans of two different services, using context propogation, I am not able to do it successfully.
I have used following code:
// at client side:
public static void sendContext(String resource) {
TextMapSetter<HttpURLConnection> setter =
new TextMapSetter<HttpURLConnection>() {
#Override
public void set(HttpURLConnection carrier, String key, String value) {
carrier.setRequestProperty(key, value);
}
};
HttpURLConnection transportLayer = null;
String urlString = "http://127.0.0.1:8080" + resource;
try {
URL url = new URL(urlString);
transportLayer = (HttpURLConnection) url.openConnection();
} catch (MalformedURLException ex) {
System.out.println(ex.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
}
GlobalOpenTelemetry.getPropagators()
.getTextMapPropagator()
.inject(Context.current(), transportLayer, setter);
}
// at server side:
public static Context getContext(HttpServletRequest request) {
TextMapGetter<HttpServletRequest> getter =
new TextMapGetter<HttpServletRequest>() {
#Override
public String get(HttpServletRequest carrier, String key) {
Enumeration<String> headerNames = carrier.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
System.out.println("headerNames.nextElement(): " + headerName);
if (headerName.equals(key)) {
String headerValue = request.getHeader(headerName);
System.out.println("headerValue): " + headerValue);
return headerValue;
}
}
}
return null;
}
#Override
public Iterable<String> keys(HttpServletRequest carrier) {
Set<String> set = new HashSet<String>();
Enumeration<String> headerNames = carrier.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
set.add(headerNames.nextElement());
}
}
return set;
}
};
Context extractedContext =
GlobalOpenTelemetry.getPropagators()
.getTextMapPropagator()
.extract(Context.current(), request, getter);
At server, i am not able to get parent span.
Kindly help on this.

You can refer to OpenTelemetry main documentation from here. It contains the context propagation part but I used HttpHeader type getter as the TextMapGetter with the same functionality which shows in the doc and instead of using
Scope scope = extractedContext.makeCurrent()
as the scope to create a child span, better to use directly without the scope,
tracer.spanBuilder(spanName).setParent(extractedContext)
Because sometimes the automated way to propagate the parent span on the current thread does not work fine.

Related

DCM4CHE, Network operations,Handling a C-Move call

Hi I'm trying to make a PACS server using Java. dcm4che appears to be quite popular. But I'm unable to find any good examples about it.
As a starting point I inspected dcmqrscp and it successfully stores a DICOM image. But I cannot manage to handle a C-MOVE call. Here's my CMove handler. It finds requested the DICOM file adds a URL and other stuff, it doesn't throw any exception yet client doesn't receive any files.
private final class CMoveSCPImpl extends BasicCMoveSCP {
private final String[] qrLevels;
private final QueryRetrieveLevel rootLevel;
public CMoveSCPImpl(String sopClass, String... qrLevels) {
super(sopClass);
this.qrLevels = qrLevels;
this.rootLevel = QueryRetrieveLevel.valueOf(qrLevels[0]);
}
#Override
protected RetrieveTask calculateMatches(Association as, PresentationContext pc, final Attributes rq, Attributes keys) throws DicomServiceException {
QueryRetrieveLevel level = QueryRetrieveLevel.valueOf(keys, qrLevels);
try {
level.validateRetrieveKeys(keys, rootLevel, relational(as, rq));
} catch (Exception e) {
e.printStackTrace();
}
String moveDest = rq.getString(Tag.MoveDestination);
final Connection remote = new Connection("reciverAE",as.getSocket().getInetAddress().getHostAddress(), 11113);
if (remote == null)
throw new DicomServiceException(Status.MoveDestinationUnknown, "Move Destination: " + moveDest + " unknown");
List<T> matches = DcmQRSCP.this.calculateMatches(keys);
if (matches.isEmpty())
return null;
AAssociateRQ aarq;
Association storeas = null;
try {
aarq = makeAAssociateRQ(as.getLocalAET(), moveDest, matches);
storeas = openStoreAssociation(as, remote, aarq);
} catch (Exception e) {
e.printStackTrace();
}
BasicRetrieveTask<T> retrieveTask = null;
retrieveTask = new BasicRetrieveTask<T>(Dimse.C_MOVE_RQ, as, pc, rq, matches, storeas, new BasicCStoreSCU<T>());
retrieveTask.setSendPendingRSPInterval(getSendPendingCMoveInterval());
return retrieveTask;
}
private Association openStoreAssociation(Association as, Connection remote, AAssociateRQ aarq)
throws DicomServiceException {
try {
return as.getApplicationEntity().connect(as.getConnection(),
remote, aarq);
} catch (Exception e) {
throw new DicomServiceException(
Status.UnableToPerformSubOperations, e);
}
}
private AAssociateRQ makeAAssociateRQ(String callingAET,
String calledAET, List<T> matches) {
AAssociateRQ aarq = new AAssociateRQ();
aarq.setCalledAET(calledAET);
aarq.setCallingAET(callingAET);
for (InstanceLocator match : matches) {
if (aarq.addPresentationContextFor(match.cuid, match.tsuid)) {
if (!UID.ExplicitVRLittleEndian.equals(match.tsuid))
aarq.addPresentationContextFor(match.cuid,
UID.ExplicitVRLittleEndian);
if (!UID.ImplicitVRLittleEndian.equals(match.tsuid))
aarq.addPresentationContextFor(match.cuid,
UID.ImplicitVRLittleEndian);
}
}
return aarq;
}
private boolean relational(Association as, Attributes rq) {
String cuid = rq.getString(Tag.AffectedSOPClassUID);
ExtendedNegotiation extNeg = as.getAAssociateAC().getExtNegotiationFor(cuid);
return QueryOption.toOptions(extNeg).contains(
QueryOption.RELATIONAL);
}
}
I added the code below to send a DICOM file as a response:
String cuid = rq.getString(Tag.AffectedSOPClassUID);
String iuid = rq.getString(Tag.AffectedSOPInstanceUID);
String tsuid = pc.getTransferSyntax();
try {
DcmQRSCP.this.as=as;
File f = new File("D:\\dcmqrscpTestDCMDir\\1.2.840.113619.2.30.1.1762295590.1623.978668949.886\\1.2.840.113619.2.30.1.1762295590.1623.978668949.887\\1.2.840.113619.2.30.1.1762295590.1623.978668949.888");
FileInputStream in = new FileInputStream(f);
InputStreamDataWriter data = new InputStreamDataWriter(in);
// !1! as.cmove(cuid,1,keys,tsuid,"STORESCU");
as.cstore(cuid,iuid,1,data,tsuid,rspHandlerFactory.createDimseRSPHandler(f));
} catch (Exception e) {
e.printStackTrace();
}
Throws this exception
org.dcm4che3.net.NoRoleSelectionException: No Role Selection for SOP Class 1.2.840.10008.5.1.4.1.2.2.2 - Study Root Query/Retrieve Information Model - MOVE as SCU negotiated
You should add a role to the application instance like:
applicationEntity.addTransferCapability(
new TransferCapability(null, "*", TransferCapability.Role.SCP, "*"));

Archive is not starting in opentok?

I am using Open tok rest api. and specifying " archiveMode:always " while creating session and they have specified in documentation that as soon as any one subscribe to session it will start archiving the session but it is not my code is as follows
final WSRequest request = WS.url("https://api.opentok.com/session/create");
// request.setContentType("application/json");
request.setHeader("X-TB-PARTNER-AUTH", Constants.OPENTOK_API_KEY+":"+Constants.OPENTOK_SECRET);
request.setHeader("archiveMode","always");
request.setMethod("POST");
final Promise<WSResponse> response = request.execute(); //post("X-TB-PARTNER-AUTH:"+ApiCredentials.apiKey+":"+ApiCredentials.apiSecret);
final Function<WSResponse,Document> resultFromResponse =
new Function<WSResponse , Document >() {
#Override
public Document apply(final WSResponse arg0) throws Throwable {
// TODO Auto-generated method stub
//String message = response.get(0).asXml().getBaseURI();
Logger.debug(""+response.get(0).getBody());
final Document doc = response.get(0).asXml();
final Result result =ok("temp value");
return doc;
}
};
final Promise<Document> resultDoc= response.map(resultFromResponse);
final Document document = resultDoc.get(1000*10l);
if(document == null) {
return null;
} else {
Logger.debug("document:"+document);
final String name = XPath.selectText("//session_id", document);
Logger.debug("sessionid:"+name);
if(name == null) {
return null;
} else {
sessionId = name;
//return ok("Hello " + name);
}
}
The "archiveMode" key is not an HTTP header, it's part of the HTTP POST body.

How to do an HTTP Post in Android to web api

I am trying to do a post to web api from android. The below is the code that I am using in android. The code is running without exception however the data is not inserted to the database. I included the code that I am using.
#Override
protected List doInBackground(Void... params)
{
List userDetails3 = new ArrayList();
URL url = null;
String urlshared = "http://10.0.0.9/MyWebApi/api/Student/PostAddStudent?userName="+"s4"+"&"+"password="+"1234"+"&"+"firsName="+"z"+"&"+"lastName="+"g"+"&"+"telephone="+"9160000000"+"&"+"address="+"2300 xxx"+"&"+"aliasMailId="+"s1.xx"+"&"+"emailId="+"xx#gmail.com"+"&"+"skypeId="+"z.g"+"";
try {
url = new URL(urlshared);
}
catch (MalformedURLException exception)
{
exception.printStackTrace();
}
HttpURLConnection httpURLConnection = null;
DataOutputStream dataOutputStream = null;
try
{
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
httpURLConnection.setRequestMethod("POST");
PrintWriter out = new PrintWriter(httpURLConnection.getOutputStream()); // this code is executed without exception
}
catch (IOException exception)
{
exception.printStackTrace();
}
return userDetails3; // (in debug) the code will run successfuly till here without exception
}
I am trying to access the PostAddStudent in the webapi. The below is my implementation of the controller and I excluded the codes inside the methods. For your information, I did test "PostAddStudent" and the other methods in the RegisterController by using the postman and they are working fine and the data inserted to database.
public class RegisterController : ApiController
{
public IEnumerable<Register> GetRegisterAuth(string userName,string password)
{
//return instance of register
}
public IEnumerable<Register> GetRegisterByUserName(string userName)
{
//return instance of register
}
public HttpResponseMessage PostAddInstructor(string instUserName, string instPassword, string instFirsName, string instLastName, string instTelephone, string instAddress, string instAliasMailId, string instEmailId, string instSkypeId)
{
//add to database and if okay will return System.Net.HttpStatusCode.Created
var response = Request.CreateResponse<Instructor>(System.Net.HttpStatusCode.Created, inst);
//if error exist then just return Badrequest
var response = Request.CreateResponse<Instructor>(System.Net.HttpStatusCode.BadRequest, inst);
}
public HttpResponseMessage PostAddStudent(string userName, string password, string firsName, string lastName, string telephone, string address, string aliasMailId, string emailId, string skypeId)
{
//add to database and if okay will return System.Net.HttpStatusCode.Created
var response = Request.CreateResponse<Instructor>(System.Net.HttpStatusCode.Created, inst);
//if error exist then just return Badrequest
var response = Request.CreateResponse<Instructor>(System.Net.HttpStatusCode.BadRequest, inst);
}
}
the below is the RouteConfig
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
//config.EnableSystemDiagnosticsTracing();
}
}
the below is the WebApiConfig
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
I need the android code that can do the post to PostAddStudent.
thanks

How to get Current Absolute URL with Query String in JSF?

I am trying to get the absolute URL in my managed bean's action listener. I have used:
HttpServletRequest#getRequestURL() // returning http://localhost:7101/POSM/pages/catalog-edit
HttpServetRequest#getQueryString() // returning _adf.ctrl-state=gfjk46nd7_9
But the actual URL is: http://localhost:7101/POSM/pages/catalog-edit?_adf.ctrl-state=gfjk46nd7_9&articleReference=HEN00067&_afrLoop=343543687406787. I don't know why the parameter artcileReference get omitted.
Is there any method which can give me the whole URL at once? How can I get the whole URL with all query string?
You can reconstruct your URL manually by using ServletRequest#getParameterNames() and ServletRequest#getParameter() both available with the HttpServletRequest instance.
Here is a sample code I've used in the past for this exact purpose :
private String getURL()
{
Enumeration<String> lParameters;
String sParameter;
StringBuilder sbURL = new StringBuilder();
Object oRequest = FacesContext.getCurrentInstance().getExternalContext().getRequest();
try
{
if(oRequest instanceof HttpServletRequest)
{
sbURL.append(((HttpServletRequest)oRequest).getRequestURL().toString());
lParameters = ((HttpServletRequest)oRequest).getParameterNames();
if(lParameters.hasMoreElements())
{
if(!sbURL.toString().contains("?"))
{
sbURL.append("?");
}
else
{
sbURL.append("&");
}
}
while(lParameters.hasMoreElements())
{
sParameter = lParameters.nextElement();
sbURL.append(sParameter);
sbURL.append("=");
sbURL.append(URLEncoder.encode(((HttpServletRequest)oRequest).getParameter(sParameter),"UTF-8"));
if(lParameters.hasMoreElements())
{
sbURL.append("&");
}
}
}
}
catch(Exception e)
{
// Do nothing
}
return sbURL.toString();
}
Here I came up with my solution, taking idea of the answer given by Alexandre, considering that HttpServletRequest#getParameterValues() method:
protected String getCurrentURL() throws UnsupportedEncodingException {
Enumeration parameters = getServletRequest().getParameterNames();
StringBuffer urlBuffer = new StringBuffer();
urlBuffer.append(getServletRequest().getRequestURL().toString());
if(parameters.hasMoreElements()) {
if(!urlBuffer.toString().contains("?")) {
urlBuffer.append("?");
} else {
urlBuffer.append("&");
}
}
while(parameters.hasMoreElements()) {
String parameter = (String)parameters.nextElement();
String[] parameterValues = getServletRequest().getParameterValues(parameter);
if(!CollectionUtils.sizeIsEmpty(parameterValues)) {
for(int i = 0; i < parameterValues.length; i++) {
String value = parameterValues[i];
if(StringUtils.isNotBlank(value)) {
urlBuffer.append(parameter);
urlBuffer.append("=");
urlBuffer.append(URLEncoder.encode(value, "UTF-8"));
if((i + 1) != parameterValues.length) {
urlBuffer.append("&");
}
}
}
}
if(parameters.hasMoreElements()) {
urlBuffer.append("&");
}
}
return urlBuffer.toString();
}

How to encapsulate the logic of parametrized messages?

I'm using java.util.resourcebundle to format my JSTL messages and this works fine:
I use the class MessageFormat you can see here. Now I want to encapsulate this to a method that is just getParametrizedMessage(String key, String[]parameters) but I'm not sure how to do it. Now there is quite a lot of work to display just one or two messages with parameters:
UserMessage um = null;
ResourceBundle messages = ResourceBundle.getBundle("messages");
String str = messages.getString("PF1");
Object[] messageArguments = new String[]{nyreg.getNummer()};
MessageFormat formatter = new MessageFormat("");
formatter.applyPattern(messages.getString("PI14"));
String outputPI14 = formatter.format(messageArguments);
formatter.applyPattern(messages.getString("PI15"));
String outputPI15 = formatter.format(messageArguments)
if(ipeaSisFlag)
if(checkIfPCTExistInDB && nyreg.isExistInDB()) {
//um = new ExtendedUserMessage(MessageHandler.getParameterizedMessage("PI15", new String[]{nyreg.getNummer()}) , UserMessage.TYPE_INFORMATION, "Info");
um = new ExtendedUserMessage(outputPI15 , UserMessage.TYPE_INFORMATION, "Info");
…and so on. Now can I move this logic to a static class MessageHandler.getParameterizedMessage that now is not working and looking like this:
private final static String dictionaryFileName="messages.properties";
public static String getParameterizedMessage(String key, String [] params){
if (dictionary==null){
loadDictionary();
}
return getParameterizedMessage(dictionary,key,params);
}
private static void loadDictionary(){
String fileName = dictionaryFileName;
try {
dictionary=new Properties();
InputStream fileInput = MessageHandler.class.getClassLoader().getResourceAsStream(fileName);
dictionary.load(fileInput);
fileInput.close();
}
catch(Exception e) {
System.err.println("Exception reading propertiesfile in init "+e);
e.printStackTrace();
dictionary=null;
}
}
How can I make using my parametrized messages as easy as calling a method with key and parameter?
Thanks for any help
Update
The logic comes from an inherited method that in in the abstract class that this extends. The method looks like:
protected static String getParameterizedMessage(Properties dictionary,String key,String []params){
if (dictionary==null){
return "ERROR";
}
String msg = dictionary.getProperty(key);
if (msg==null){
return "?!Meddelande " +key + " saknas!?";
}
if (params==null){
return msg;
}
StringBuffer buff = new StringBuffer(msg);
for (int i=0;i<params.length;i++){
String placeHolder = "<<"+(i+1)+">>";
if (buff.indexOf(placeHolder)!=-1){
replace(buff,placeHolder,params[i]);
}
else {
remove(buff,placeHolder);
}
}
return buff.toString();
}
I think I must rewrite the above method in order to make it work like a resourcebundle rather than just a dictionary.
Update 2
The code that seems to work is here
public static String getParameterizedMessage(String key, Object [] params){
ResourceBundle messages = ResourceBundle.getBundle("messages");
MessageFormat formatter = new MessageFormat("");
formatter.applyPattern(messages.getString(key));
return formatter.format(params);
}
I'm not really sure what you're trying to achive, here's what I did in the past:
public static final String localize(final Locale locale, final String key, final Object... param) {
final String name = "message";
final ResourceBundle rb;
/* Resource bundles are cached internally,
never saw a need to implement another caching level
*/
try {
rb = ResourceBundle.getBundle(name, locale, Thread.currentThread()
.getContextClassLoader());
} catch (MissingResourceException e) {
throw new RuntimeException("Bundle not found:" + name);
}
String keyValue = null;
try {
keyValue = rb.getString(key);
} catch (MissingResourceException e) {
// LOG.severe("Key not found: " + key);
keyValue = "???" + key + "???";
}
/* Message formating is expensive, try to avoid it */
if (param != null && param.length > 0) {
return MessageFormat.format(keyValue, param);
} else {
return keyValue;
}
}

Categories