How to set "SAP-PASSPORT" Header in OData call with Cloud SDK Neo project template - sap-cloud-sdk

We are going to gather some statics in SAP BTP Neo environment with FRun (not support CF). To implement the tracing of outgoing connections calls. I need to update "SAP-PASSPORT" and forward it as a header.
I followed SAP official documentation to implement it.
https://help.sap.com/viewer/ea72206b834e4ace9cd834feed6c0e09/Cloud/en-US/05a07108d34540d39b8a79e2caf96c8c.html
From my perspective, Step 2 could be skipped. The only thing I need to do is to get updated SAP Passport Header and set it to request header.
Sample code:
1.Implement ConnectionInfo interface
public class ConnectionInfoNeo implements ConnectionInfo {
#Override
public byte[] getId() {
UUID uuid = java.util.UUID.randomUUID();
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(uuid.getMostSignificantBits());
bb.putLong(uuid.getLeastSignificantBits());
return bb.array();
}
#Override
public int getCounter() {
return 1;
}
}
Get SapPassportHeader and set it to request header
public class MyPurchaseOrderService {
private static final Logger logger = LoggerFactory.getLogger(MyPurchaseOrderService.class);
private static final ConnectionInfo CONNECTION_INFO = new ConnectionInfoNeo();
public List<String> getPurchaseOrdersValueHelp(String purOrderStr) throws NamingException {
String destinationName = "ErpQueryEndpoint";
Context ctx = new InitialContext();
logger.info("Context: " + ctx);
// ConnectivityConfiguration configuration = (ConnectivityConfiguration) ctx.lookup("java:comp/env/connectivityConfiguration");
// DestinationConfiguration destConfiguration = configuration.getConfiguration(destinationName);
// String destinationUrl = destConfiguration.getProperty("URL");
SapPassportHeader sapPassportHeader = updateSapPassportHeader(ctx);
HttpDestination destination = DestinationAccessor.getDestination(destinationName).asHttp();
List<PurchaseOrder> purchaseOrders = new DefaultPurchaseOrderService()
.getAllPurchaseOrder()
.withHeader("SAP-PASSPORT", sapPassportHeader.getValue())
.filter(PurchaseOrder.PURCHASE_ORDER.startsWith(purOrderStr))
//.top(20)
.executeRequest(destination);
List<String> purOrderNumList = new ArrayList<>();
purchaseOrders.forEach(purchaseOrder -> {
purOrderNumList.add(purchaseOrder.getPurchaseOrder());
});
return purOrderNumList;
}
private SapPassportHeader updateSapPassportHeader(Context ctx) throws NamingException {
SapPassportHeaderProvider sapPassportHeaderProvider = (SapPassportHeaderProvider) ctx.lookup("java:comp/env/SapPassportHeaderProvider");
return sapPassportHeaderProvider.getSapPassportHeader(CONNECTION_INFO);
}
}
But when I tested in Neo environment, I got an exception.
2021 11 04 03:05:11#+00#ERROR#java.lang.Throwable##ZJE8SZH#https-jsse-nio-8041-exec-6#na#s3td7fnnd5#purchaseorderneoapplication#web#s3td7fnnd5#na#na#na#na#javax.naming.NameNotFoundException: Name [SapPassportHeaderProvider] is not bound in this Context. Unable to find [SapPassportHeaderProvider]. |
2021 11 04 03:05:11#+00#ERROR#java.lang.Throwable##ZJE8SZH#https-jsse-nio-8041-exec-6#na#s3td7fnnd5#purchaseorderneoapplication#web#s3td7fnnd5#na#na#na#na# at org.apache.naming.NamingContext.lookup(NamingContext.java:824) |
2021 11 04 03:05:11#+00#ERROR#java.lang.Throwable##ZJE8SZH#https-jsse-nio-8041-exec-6#na#s3td7fnnd5#purchaseorderneoapplication#web#s3td7fnnd5#na#na#na#na# at org.apache.naming.NamingContext.lookup(NamingContext.java:157) |
2021 11 04 03:05:11#+00#ERROR#java.lang.Throwable##ZJE8SZH#https-jsse-nio-8041-exec-6#na#s3td7fnnd5#purchaseorderneoapplication#web#s3td7fnnd5#na#na#na#na# at org.apache.naming.NamingContext.lookup(NamingContext.java:834) |
2021 11 04 03:05:11#+00#ERROR#java.lang.Throwable##ZJE8SZH#https-jsse-nio-8041-exec-6#na#s3td7fnnd5#purchaseorderneoapplication#web#s3td7fnnd5#na#na#na#na# at org.apache.naming.NamingContext.lookup(NamingContext.java:157) |
2021 11 04 03:05:11#+00#ERROR#java.lang.Throwable##ZJE8SZH#https-jsse-nio-8041-exec-6#na#s3td7fnnd5#purchaseorderneoapplication#web#s3td7fnnd5#na#na#na#na# at org.apache.naming.NamingContext.lookup(NamingContext.java:834) |
2021 11 04 03:05:11#+00#ERROR#java.lang.Throwable##ZJE8SZH#https-jsse-nio-8041-exec-6#na#s3td7fnnd5#purchaseorderneoapplication#web#s3td7fnnd5#na#na#na#na# at org.apache.naming.NamingContext.lookup(NamingContext.java:171) |
2021 11 04 03:05:11#+00#ERROR#java.lang.Throwable##ZJE8SZH#https-jsse-nio-8041-exec-6#na#s3td7fnnd5#purchaseorderneoapplication#web#s3td7fnnd5#na#na#na#na# at org.apache.naming.SelectorContext.lookup(SelectorContext.java:161) |
2021 11 04 03:05:11#+00#ERROR#java.lang.Throwable##ZJE8SZH#https-jsse-nio-8041-exec-6#na#s3td7fnnd5#purchaseorderneoapplication#web#s3td7fnnd5
#na#na#na#na# at javax.naming.InitialContext.lookup(InitialContext.java:417) |
How to register SapPassportHeaderProvider in JNDI? Is there any simple way to get the header in Cloud SDK Neo for Java7 project?
================================================================
I added some resource configuration in web.xml. The above issue is resolved. But SAP passport header is always null.
<resource-ref>
<res-ref-name>connectivityConfiguration</res-ref-name>
<res-type>com.sap.core.connectivity.api.configuration.ConnectivityConfiguration</res-type>
</resource-ref>
<resource-ref>
<res-ref-name>SapPassportHeaderProvider</res-ref-name>
<res-type>com.sap.core.connectivity.api.sappassport.SapPassportHeaderProvider</res-type>
</resource-ref>
2021 11 04 04:14:58#+00#ERROR#org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/PurchaseOrderNeo-application].[com.bosch.sbs.po.servet.PurchaseOrderValueHelpServlet]##ZJE8SZH#https-jsse-nio-8041-exec-7#na#s3td7fnnd5#purchaseorderneoapplication#web#s3td7fnnd5#na#na#na#na#Servlet.service() for servlet [com.bosch.sbs.po.servet.PurchaseOrderValueHelpServlet] in context with path [/PurchaseOrderNeo-application] threw exception com.sap.cloud.sdk.cloudplatform.exception.ShouldNotHappenException: com.sap.cloud.sdk.cloudplatform.thread.exception.ThreadContextExecutionException: java.lang.NullPointerException: while trying to invoke the method com.sap.core.connectivity.api.sappassport.SapPassportHeader.getValue() of a null object loaded from local variable 'sapPassportHeader'
=========================================================================

Since you tagged your question with sap-cloud-sdk, I would respond on behalf of the library.
It works independent form the API provided by [SAP official documentation][2]. You would just need to add the SAP internal dependency com.sap.cloud.sdk.cloudplatform:sap-passport into your project. As long as you are using the Destination API the respective headers are added automatically to your outgoing requests.

Related

Issue with no log4net Logger.Appenders even though log shows config successfully loaded

I would appreciate any help you can provide? Not sure what I am doing wrong...
I am creating a log4net compatibility library for my new Visual Studio tool ErrorUnit at https://github.com/JohnGoldInc/ErrorUnit.Logger_log4net
Line 37 of https://github.com/JohnGoldInc/ErrorUnit.Logger_log4net/blob/master/ErrorUnitLogger.cs has Count=0 Appenders even though my log shows that appenders were loaded:
16 namespace ErrorUnit.Logger_log4net
17 {
18 public class ErrorUnitLogger : ILogger
19 {
20 private static ILog log = LogManager.GetLogger(typeof(ErrorUnitLogger));
21
22 public IEnumerable<string> GetErrorUnitJson(DateTime afterdate)
23 {
24 var ErrorUnitJson = new ConcurrentBag<string>();
25 log4net.Util.LogLog.InternalDebugging = true; //todo remove
26 System.Diagnostics.Trace.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(#"f:\Temp\Logger_log4net.log", "myListener"));
27 System.Diagnostics.Trace.AutoFlush = true;
28 System.Diagnostics.Trace.TraceInformation("Test Logger_log4net message.");
29
30 var config = log4net.Config.XmlConfigurator.Configure();
31 log = LogManager.GetLogger(typeof(ErrorUnitLogger));
32
33 // Parallel.ForEach(logs, log => {
34 var log4net_Logger = log.Logger as log4net.Repository.Hierarchy.Logger;
35 if (log4net_Logger != null)
36 {
37 Parallel.ForEach(log4net_Logger.Appenders.Cast<log4net.Appender.IAppender>(), appender =>
For the log ( the log without ellipsis is at https://github.com/JohnGoldInc/ErrorUnit.Logger_log4net/blob/master/README.md ):
devenv.exe Information: 0 : Test Logger_log4net message.
log4net: configuring repository [log4net-default-repository] using .config file section
log4net: Application config file is [F:\Documents\Visual Studio 2015\Projects\WebApplication1\WebApplication1.Tests\obj\Release]
log4net: Configuring Repository [log4net-default-repository]
log4net: Configuration update mode [Merge].
...
log4net: Created Appender [AdoNetAppender]
log4net: Adding appender named [AdoNetAppender] to logger [root].
log4net: Hierarchy Threshold []
...
Thanks!
Was not looking at top level Logger, to get to top level logger refer to .Parent property:
var log4net_Logger = log.Logger as log4net.Repository.Hierarchy.Logger;
while (log4net_Logger != null && log4net_Logger.Appenders.Count == 0)
log4net_Logger = log4net_Logger.Parent;
I do not have enough reputation to add a comment to your answer... so adding a new answer here but this is more so a comment
From your log, it seems you are adding AdoNetAppender to the 'root' Logger, so if you wish to get all the appenders for 'root' you may need to access the 'root' logger (which sits at the top of the hierarchy). Accessing the parent Logger, in this case, worked for you because 'root' happens to be parent of ErrorUnitLogger you have...but that may not always be true in general
If you are not already aware, you can access 'root' logger like this
Hierarchy hierarchy = (Hierarchy)log4net.LogManager.GetRepository();
Logger rootLogger = hierarchy.Root;
You are sending your test message before you configure log4net. First configure log4net and than send the test trace message:
System.Diagnostics.Trace.TraceInformation("Test Logger_log4net message.");

storing objects in hazelcast

I am trying to store my object in Hazelcast map but its not working. It creates a new instance which i am able to see in console and mancenter as well. It also creates the map but it has nothing inside. Also, System.out.println (accountMap.get()) prints nothing.
I even tried by doing a put operation with simple string, still same result.
Here is my code:
userAccount user = new userAccount();
user.name = "pras";
user.pass = "12345";
HazelcastInstance instance = Hazelcast.newHazelcastInstance (new Config());
Map<Integer, userAccount> accountMap = instance.getMap("userMap");
accountMap.put(1, user);
System.out.println (accountMap.get(1));
Given:
package com.hazelcast;
import java.io.Serializable;
public class userAccount implements Serializable {
String name;
String pass;
}
And your code from above, I get the following output:
INFO: [192.168.1.70]:5701 [dev] [3.8.1]
Members [1] {
Member [192.168.1.70]:5701 - f8f3cf77-9b02-48b7-8a61-f353c40a6267 this
}
Apr 21, 2017 3:19:28 PM com.hazelcast.core.LifecycleService
INFO: [192.168.1.70]:5701 [dev] [3.8.1] [192.168.1.70]:5701 is STARTED
Apr 21, 2017 3:19:28 PM com.hazelcast.internal.partition.impl.PartitionStateManager
INFO: [192.168.1.70]:5701 [dev] [3.8.1] Initializing cluster partition table arrangement...
com.hazelcast.userAccount#70ab80e3
Hope this helps

JSF 2.2: Configure available Locales outside faces-config.xml

Currently i have a section in my faces-config.xml such as follows:
<locale-config>
<default-locale>en</default-locale>
<supported-locale>en_US</supported-locale>
<supported-locale>en_GB</supported-locale>
<supported-locale>de</supported-locale>
<supported-locale>de_DE</supported-locale>
</locale-config>
This is working as intended.
The problem is, i have to be able to define these Locales whithout touching the faces-config.xml in my war. The idea is having e.g. a config File on the resource Path defining all the available Locales.
I already tried an programatic approach as well as using a second faces-config.xml in the META-INF of another module i have access to and defining an specific file on the ressource path which should be merged according to this article. The second file in each case contained the above section in a valid faces-config.xml format. Both without any effect (neither errors nor any change in the behaviour)
Is there any nice way to do this without touching the original faces-config?
I am able to change the ear module and to access ressources programatically in any location. Unfortunately adjusting the faces-config.xml in the .war is no option.
There is a misconception here as far as I can see. There is no need to configure anything in the locale-config if you use custom resolvers/resource bundles/whatever and have otherwise full control over things.
If you look at the answer in Add Resource Bundles Programmatically, you see the OmniFaces Faces.getLocale() is used to pass a locale to the resourceBundle
Locale userLocale = Faces.getLocale();
ResourceBundle b = ResourceBundle.getBundle("msgs", userLocale);
So what is effectively done is pass a programmatically chosen locale to it, not automagically using something that is configured in the locale-config.
The fact the IN Faces.getLocale() some code is present to use the locale-config is to make sure it can be used when people have something configured in locale-config, so it behaves as expected in plain normal JSF. In line 16 it retreives the locale send in the request by the user. In line 18 it checks this against the supported-locale (can be left out in a custom implementation!!!) and if no match, use the default-locale (can be left out to, as can line 7-12)
1 /**
2 * {#inheritDoc}
3 * #see Faces#getLocale()
4 */
5 public static Locale getLocale(FacesContext context) {
6 Locale locale = null;
7 UIViewRoot viewRoot = context.getViewRoot();
8
9 // Prefer the locale set in the view.
10 if (viewRoot != null) {
11 locale = viewRoot.getLocale();
12 }
13
14 // Then the client preferred locale.
15 if (locale == null) {
16 Locale clientLocale = context.getExternalContext().getRequestLocale();
17
18 if (getSupportedLocales(context).contains(clientLocale)) {
19 locale = clientLocale;
20 }
21 }
22
23 // Then the JSF default locale.
24 if (locale == null) {
25 locale = context.getApplication().getDefaultLocale();
26 }
27
28 // Finally the system default locale.
29 if (locale == null) {
30 locale = Locale.getDefault();
31 }
32
33 return locale;
34 }
So this code can be totally tweaked to your liking, including first checking if the user has configured a locale of preference in your application and otherwise using the locale send by the browser IF supported.

How to create service builder for liferay plugin project with maven

I have Already create Liferay Plugin project. and maven install also over.
it gives
------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ---------------------------------------------------------------------
[INFO] Total time: 1:29.773s
[INFO] Finished at: Wed Jun 17 15:46:10 IST 2015
[INFO] Final Memory: 34M/151M
[INFO] -----------------------------.
But unable to add service builder.
When i try to add service builder
new->Liferay service builder.
It does not showing any plugin project.
Then how to add service builder?
Frankly speaking Liferay-Maven combination is not so fully supported by Liferay IDE in eclipse. Originally Liferay IDE has been created for only ANT support but since maven support has been introduced there are many things missing.
This issue which you have raised is same for following options as well.
JSF Portlet
Layout
Theme
Service Builder
This is not an issue for following options
Hook
Portlet
Vaadin Portlet
So, best way is to generate new service builder through maven archetypes supported for specific liferay version.
E.g com.liferay.maven.archetypes:liferay-servicebuilder-archetype:6.2.1 for liferay 6.2.1 GA2 version.
If you want to add a vaadin application to existing liferay portlet then create new LIFERAY-VAADIN project and there you can use "You can continue to use ServiceBuilder as you always have, and retrieve data from your services using XXXXXServiceUtil (or XXXXXLocalServiceUtil)." You may also want to check here, and here.
For example here is one DatabaseUtil class from vaadin.
import java.awt.List;
import java.util.ArrayList;
import com.vaadin.data.util.HierarchicalContainer;
public class DatabaseUtil {
public static HierarchicalContainer fillTree_db() {
HierarchicalContainer container = new HierarchicalContainer();
ArrayList < ArrayList < String >> treeNodes = new ArrayList < ArrayList < String >> ();
try {
List < TREEVIEW > nodes = TREEVIEWLocalServiceUtil.getAllNodes();
for (TREEVIEW node: nodes) {
String nodename = node.getNodename();
ArrayList < String > row = new ArrayList < String > ();
row.add(String.valueOf(node.getNodeid()));
row.add(node.getNodename());
row.add(String.valueOf(node.getRootid()));
container.addItem(nodename);
treeNodes.add(row);
}
for (int i = 0; i < treeNodes.size(); i++) {
int root = 0;
root = Integer.parseInt(treeNodes.get(i).get(2));
if (root != 0)
container.setParent(treeNodes.get(i).get(1),
treeNodes.get(root - 1).get(1));
}
} catch (Exception e) {
System.err.println("Exception: " + e.getMessage());
} finally {}
return container;
}
}

CRM 2011 PLUGIN to update another entity

My PLUGIN is firing on Entity A and in my code I am invoking a web service that returns an XML file with some attributes (attr1,attr2,attr3 etc ...) for Entity B including GUID.
I need to update Entity B using the attributes I received from the web service.
Can I use Service Context Class (SaveChanges) or what is the best way to accomplish my task please?
I would appreciate it if you provide an example.
There is no reason you need to use a service context in this instance. Here is basic example of how I would solve this requirement. You'll obviously need to update this code to use the appropriate entities, implement your external web service call, and handle the field updates. In addition, this does not have any error checking or handling as should be included for production code.
I made an assumption you were using the early-bound entity classes, if not you'll need to update the code to use the generic Entity().
class UpdateAnotherEntity : IPlugin
{
private const string TARGET = "Target";
public void Execute(IServiceProvider serviceProvider)
{
//PluginSetup is an abstraction from: http://nicknow.net/dynamics-crm-2011-abstracting-plugin-setup/
var p = new PluginSetup(serviceProvider);
var target = ((Entity) p.Context.InputParameters[TARGET]).ToEntity<Account>();
var updateEntityAndXml = GetRelatedRecordAndXml(target);
var relatedContactEntity =
p.Service.Retrieve(Contact.EntityLogicalName, updateEntityAndXml.Item1, new ColumnSet(true)).ToEntity<Contact>();
UpdateContactEntityWithXml(relatedContactEntity, updateEntityAndXml.Item2);
p.Service.Update(relatedContactEntity);
}
private static void UpdateContactEntityWithXml(Contact relatedEntity, XmlDocument xmlDocument)
{
throw new NotImplementedException("UpdateContactEntityWithXml");
}
private static Tuple<Guid, XmlDocument> GetRelatedRecordAndXml(Account target)
{
throw new NotImplementedException("GetRelatedRecordAndXml");
}
}

Resources